checkout流程中的用戶信息與地址信息表單是經過LayoutProcessor提供數據並利用前端的uiElement繪製表單元素,因此不能用傳統的方法給表單元素追加驗證器與行爲。javascript
vendor/magento/module-ui/view/base/web/js/lib/validation/rules.js
以上腳本就是uiElement的驗證器集合,能夠重寫此腳本並追加新的驗證器,假設咱們添加名爲validate-checkout-phone的驗證器。php
以實現電話號碼每三位隔一個空格的需求,須要寫成ko組件,並改寫element模板。html
先編寫KO組件前端
define(['jquery','ko'], function($, ko) { ko.bindingHandlers.phone = { init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { if(element.tagName == 'INPUT') { $(element).on('keyup', function(e){ if(e.keyCode >= 48 && e.keyCode <=90 && this.value) { var _value = this.value; var charArr = _value.replace(/ /g, '').split(''); for(var i=1; i<charArr.length; i++) { if(i % 3 == 0) { charArr[i] = ' '+charArr[i]; } } this.value = charArr.join(''); } }); } } }; }
因爲KO組件須要用data-bind把組件綁定到元素上,因此須要替換原來的元素模板才能實現app/design/frontend/<theme>/default/Magento_Ui/web/templates/form/element/phone.html
java
<input class="input-text" type="text" data-bind=" phone: true, value: value, valueUpdate: 'keyup', hasFocus: focused, attr: { name: inputName, placeholder: placeholder, 'aria-describedby': noticeId, id: uid, disabled: disabled }" />
以上已經把驗證器與動做器都寫好了,就得把它們接上表單元素,要實現這一點須要先查得LayoutProcessor數據,個人作法是在 app/design/frontend/<theme>/default/Magento_Checkout/templates/onepage.phtml
裏打印出jsLayout,就會查出如下數據:
驗證器數據
jquery
表單元素模板數據
web
查出元素數據後才能知道目標數據的位置,由於jsLayout數據是個巨大的須要。有了數據後就能夠編寫出如下代碼app
<?xml version="1.0" ?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Checkout\Block\Checkout\LayoutProcessor"> <plugin name="checkout_change" type="Infinity\Checkout\Plugin\Magento\Checkout\Block\Checkout\LayoutProcessor" /> </type> </config>
namespace Infinity\Checkout\Plugin\Magento\Checkout\Block\Checkout; class LayoutProcessor { public function afterProcess( \Magento\Checkout\Block\Checkout\LayoutProcessor $subject, $jsLayout ) { // 接上驗證器 $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']['shippingAddress']['children']['shipping-address-fieldset']['children']['telephone']['validation']['validate-checkout-phone'] = true; // 替換新模板 $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']['shippingAddress']['children']['shipping-address-fieldset']['children']['telephone']['config']['elementTmpl'] = 'ui/form/element/phone'; } }