Проверка города и улицы при оформлении заказа

#javascript #php #magento #knockout.js #magento2

#javascript #php #magento #knockout.js #magento2

Вопрос:

Я новичок в Magento2 и сталкиваюсь со следующей задачей. Я должен выполнить пользовательскую проверку для ввода города и улицы на странице оформления заказа как для этапов доставки, так и для оплаты. Есть 2 проблемы, которые я полностью не понимаю.

  1. Как я мог исследовать, шаблоны для города и улицы вставляются нокаутом. Чтобы получить список городов и улиц, я должен вставить метод php в тег скрипта. Этот метод php предоставляет мне URL для следующего запроса Ajax. Из-за общего шаблона нокаута с типом ‘.html’ я не могу вставить туда php-код. Итак, как я могу вызвать свой js-файл из html-шаблона Knockout?
  2. Входные данные города и улицы должны предлагать совпадения для первых введенных букв (в результате запроса Ajax) в их списках ниже. Как можно реализовать эти списки?

Я прочитал Magento devdocs и множество сообществ, но не смог найти вразумительного объяснения. Извините за возможное повторение.

app/design/frontend/Vendor/Theme/Magento_Checkout/web/template/shipping-address/form.html (входы вставляются внутрь id="shipping-new-address-form" )

 <div class="amtheme-shipping-wrap">
    <form class="form form-shipping-address amtheme-form-address"
          id="co-shipping-form"
          data-bind="attr: {'data-hasrequired': $t('* Required Fields')}">
        <div class="step-title" data-bind="text: setAddressTitle" data-role="title"></div>
        <!-- ko foreach: getRegion('before-fields') -->
            <!-- ko template: getTemplate() --><!-- /ko -->
        <!--/ko-->
        <div id="shipping-new-address-form" class="fieldset address">
            <!-- ko foreach: getRegion('additional-fieldsets') -->
                <!-- ko template: getTemplate() --><!-- /ko -->
            <!--/ko-->
            <!-- ko if: (isCustomerLoggedIn) -->
            <div class="field choice" data-bind="visible: !isFormInline">
                <input type="checkbox" class="checkbox" id="shipping-save-in-address-book" data-bind="checked: saveInAddressBook" />
                <label class="label" for="shipping-save-in-address-book">
                    <span data-bind="i18n: 'Save in address book'"></span>
                </label>
            </div>
            <!-- /ko -->
            <div class="amtheme-address-toolbar" data-bind="visible: !isFormInline amp;amp; !isFormPopUpVisible()">
                <button type="button"
                        class="action action-cancel"
                        click="hideNewAddress"
                        text="$t('Cancel')"
                        data-bind="attr: {title: $t('Cancel')}">
                </button>
                <button type="button"
                        class="action action-save"
                        click="saveNewAddress"
                        text="$t('Ship here')"
                        data-bind="attr: {title: $t('Ship here')}">
                </button>
            </div>
        </div>
    </form>
</div>
 

Я собирался написать внутри form.html что — то вроде этого:

 <script>
    require([
        'jquery',
        'Magento_Theme/js/govaddress-validation'
    ], function($) {
        $(function () {
            $('input[name="city"]').keyup(function () {
                console.log('keyup event worked');
                govAddressValidation.getCityList('<?php echo $this->getUrl("opgovaddress"); ?>');
            });
        })
    })
</script>
 

Мой JS-файл не имеет значения, поскольку на данный момент он недоступен

app/design/frontend/Vendor/Theme/Magento_Theme/web/js/govaddress-validation.js

 define([
    'jquery'
], function ($) {
    'use strict';
    return {
        url: '',
        getCityList: function (url) {
            var inputValue = $('input[name="city"]').val();
            this.inputValue = inputValue;
            this.url = url;
            this.ajaxCall();
            console.log('getCityList');
        },

        ...
    }
})
 

app/design/frontend/Vendor/Theme/Magento_Theme/requirejs-config.js

 var config = {
    map: {
        '*': {
            backTop: 'Magento_Theme/js/components/back-to-top',
            amMenu: 'Magento_Theme/js/components/am-menu',
            amQty: 'Magento_Theme/js/components/am-qty',
            amSelect: 'Magento_Theme/js/components/am-select',
            amFileUpload: 'Magento_Theme/js/components/am-file-upload',
            amStickyHeader: 'Magento_Theme/js/components/am-sticky-header',
            govAddressValidation: 'Magento_Theme/js/govaddress-validation'
        }
    },

    config: {
        mixins: {
            'mage/validation': {
                'Magento_Theme/js/lib/mage/validation-mixin': false
            },
            'mage/menu': {
                'Magento_Theme/js/lib/mage/menu-mixin': true
            }
        }
    }
};
 

Ответ №1:

Во-первых, проверка Magento для checkout_index_index.xml не работает должным образом, поэтому вам придется вставить правила при замене полей улиц. Вы можете сделать это, создав плагин и вставив поля в Layout AfterProcessor.

namespace/module/etc/frontend/di.xml

 <type name="MagentoCheckoutBlockCheckoutLayoutProcessor">
    <plugin name="rewrite-street" type="NamespaceModuleModelCheckoutLayoutProcessorPlugin" sortOrder="10"/>
</type>
 

И LayoutProcessorPlugin должен выглядеть так: (Пожалуйста, смотрите в моем приложении) https://pastebin.com/AE6AiLxk

Вы можете вставить в массив проверки любое правило проверки, которое вы хотите.

Ответ №2:

Итак, что вам нужно сделать, это открыть свою проверку и найти это поле, которое вы хотите проверить. Я выберу ваше первое поле, город. Открытие инструментов разработки дает мне это:

 <input class="input-text" type="text" data-bind=" ..." name="city" ...>
 

Итак, мы могли бы что-то сделать с именем, поскольку у нас нет действительно полезного идентификатора. Я вижу в вашем вопросе, что у вас уже есть эта часть!

Поскольку вы говорите, что хотите как этап доставки, так и этап оплаты, я пойду на последний. Итак, для этого нам нужен пользовательский валидатор на этапе оплаты. Я предполагаю, что у вас уже есть пользовательское расширение, что-то вроде Vendor_MyCheckoutValidator . Сначала мы создадим копию checkout_index_index.xml (из модуля оформления заказа Magento) в Vendor / MyCheckoutValidator / view / frontend / layout, и мы оставим все, что нам не нужно. Просто скопируйте шаги до оплаты:

 <body>
  <referenceBlock name="checkout.root">
    <arguments>
      [... all the way down to payment ...]
       <item name="payment" xsi:type="array">
         <item name="children" xsi:type="array">
           <item name="additional-payment-validators" xsi:type="array">
             <item name="children" xsi:type="array">
               <item name="my-city-validator" xsi:type="array">
                 <item name="component" xsi:type="string">Vendor_MyCheckoutValidator/js/view/finalcheck-validation</item>
                 </item>
                 [... and all the way back down again ...]
 

Итак, у вас есть это, я назвал его my-city-validator, и он указывает на Vendor_MyCheckoutValidator/js /view/finalcheck-validation .

Давайте создадим тысячи finalcheck-validation.js в вашем модуле в разделе Vendor/MyCheckoutValidator / view / frontend /web / js / view:

 define(
 [
  'uiComponent',
  'Magento_Checkout/js/model/payment/additional-validators',
  'Vendor_MyCheckoutValidator/js/model/final-address-check-validator'
 ],
  function (Component, additionalValidators, finalAddressCheckValidator) {
   'use strict';
   additionalValidators.registerValidator(finalAddressCheckValidator);
   return Component.extend({});
  }
);
 

Это выглядит сложнее, чем есть, но просто сказано, что в нашем определении говорится, что это дополнительный валидатор оплаты, его можно найти в js / model / final-address-check-validator, и затем они используются в функции. Итак, теперь нам нужен наш последний бит, final-address-check-validator.js это должно быть в Vendor /MyCheckoutValidator / view / frontend /web / js /model :

Примечание: путь, указанный в checkout_index_index.xml является ли Vendor_MyCheckoutValidator / js / view / finalcheck-validation, а в приведенном выше js это Vendor_MyCheckoutValidator / js / model / final-address-check-validator, но на самом деле вам также нужен бит «view / frontend / web» (Magento знает, где найтиэто, но это может сбить с толку новых разработчиков) поэтому наш путь — Vendor/MyCheckoutValidator /view/frontend /web / js /view и Vendor /MyCheckoutValidator /view /frontend /web /js /model

Вернемся к нашей последней части, final-address-check-validator.js . Здесь у нас есть проблема с незнанием идентификатора, но у нас есть имя ввода, как показано в начале моего сообщения, имя «город». Итак, давайте проверим, начинается ли он с Z, потому что мы не хотим отправлять данные в города, которые начинаются с Z.

Нам нужны некоторые стандартные вещи, такие как mage / translate и (ошибка) MessageList и, конечно, jquery:

 define(
['jquery', 'mage/translate', 'Magento_Ui/js/model/messageList'],
function ($, $t, messageList) {
 'use strict';
 return {
  validate: function () {
    var cityIsFine = true,
      city = $('input[name="city"]').val(); // getting our city input by name!
    if(city.match("^Z") { 
      messageList.addErrorMessage({ message: $t('We are sorry, your city starts with a Z.') });
      cityIsFine = false;
    }
    // you could do some checks here and maybe a console.log
    console.log(city);
    if(!cityIsFine) {
       return false;
    }
    return true;
   } 
  }
 }
);
    
 

Установите свой модуль, убедитесь, что очистили весь кэш! Особенно кэш интерфейса! Разверните свой интерфейс, тщательно очистите кэш браузера и попробуйте использовать город с именем Zen. Вы должны быть в состоянии заполнить все нормально, а затем вы нажимаете кнопку оплаты и получаете сообщение об ошибке!

Как вы можете видеть, я не использовал никаких шаблонов, миксинов или других вещей (я мог бы, но здесь это просто не нужно). Вам нужно только объявить свой пользовательский валидатор на этапе оплаты, добавить его к дополнительным валидаторам, как показано, и проделать в нем некоторую магию jquery.

Я сосредоточился на городе, но вы могли бы сделать то же самое для улицы. Посмотрите на свой интерфейс, как он называется. Допустим, у него есть name=»улица [0]», тогда ваше значение jQuery будет выглядеть как street0 = $(‘input[name=»улица [0]»]’).val();

Вы также можете начать с выдачи ошибки сразу и заставить ее работать, прежде чем добавлять регулярные выражения и другие правила. Тогда вы знаете, что у вас это работает 🙂

 define(
['jquery', 'mage/translate', 'Magento_Ui/js/model/messageList'],
function ($, $t, messageList) {
 'use strict';
 return {
  validate: function () {
    console.log('Sorry!');
    messageList.addErrorMessage({ message: $t('We are sorry you will never get past the payment button') });
    return false;
   }
  }
 }
);
 

И эту часть я не пробовал, но я думаю, что вы можете выполнить вызов ajax в приведенном выше валидаторе. Я не уверен, хотите ли вы какого-то автозаполнения вашего вопроса, поэтому я сосредоточился на проверке города в приведенном выше ответе.