#javascript #php #magento #knockout.js #magento2
#javascript #php #magento #knockout.js #magento2
Вопрос:
Я новичок в Magento2 и сталкиваюсь со следующей задачей. Я должен выполнить пользовательскую проверку для ввода города и улицы на странице оформления заказа как для этапов доставки, так и для оплаты. Есть 2 проблемы, которые я полностью не понимаю.
- Как я мог исследовать, шаблоны для города и улицы вставляются нокаутом. Чтобы получить список городов и улиц, я должен вставить метод php в тег скрипта. Этот метод php предоставляет мне URL для следующего запроса Ajax. Из-за общего шаблона нокаута с типом ‘.html’ я не могу вставить туда php-код. Итак, как я могу вызвать свой js-файл из html-шаблона Knockout?
- Входные данные города и улицы должны предлагать совпадения для первых введенных букв (в результате запроса 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 в приведенном выше валидаторе. Я не уверен, хотите ли вы какого-то автозаполнения вашего вопроса, поэтому я сосредоточился на проверке города в приведенном выше ответе.