magento2 checkout页面对shipping address指定字段添加自定义验证

3.07K 浏览开发笔记

magento2 checkout页面对shipping address指定字段添加自定义验证

接到客户需求,想要在用户输入street字段的时候,输入内容若包含P.O. BOX 则有相关提示:

首先想到的肯定是添加blur或者keyup事件进行输入监听,这样的话要不了几分钟就搞定了。
若遵循magento开发规范,则需要另外想法子,项目用了onestepcheckout插件,但是原理都是一样的,在主题或者自定义的module里面重写就行了。

首先用户点击place order的时候验证:

checkout_index_index:找到并且替换对应内容

<item name="additional-payment-validators" xsi:type="array">    <item name="component" xsi:type="string">uiComponent</item>    <item name="children" xsi:type="array">        <!-- Additional payment validators here -->        <item name="email-validator" xsi:type="array">            <item name="component" xsi:type="string">Aheadworks_OneStepCheckout/js/view/payment-method/email-validator</item>        </item>        <item name="agreements-validator" xsi:type="array">            <item name="component" xsi:type="string">Aheadworks_OneStepCheckout/js/view/checkout-agreements/validation</item>        </item>        <!--插入自定义验证器-->        <item name="streetValidator" xsi:type="array">            <item name="component" xsi:type="string">Aheadworks_OneStepCheckout/js/view/streetValidator</item>        </item>    </item> </item>

streetValidator注册验证器器内容:

/** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ define(    [        &#39;uiComponent&#39;,        &#39;Magento_Checkout/js/model/payment/additional-validators&#39;,        &#39;Aheadworks_OneStepCheckout/js/model/streetValidator&#39;    ],    function (Component, additionalValidators, streetValidator) {        &#39;use strict&#39;;        additionalValidators.registerValidator(streetValidator);        return Component.extend({});    } );

Aheadworks_OneStepCheckout/js/model/streetValidator.js文件内容:

define(    [        &#39;jquery&#39;,        &#39;Magento_Ui/js/model/messageList&#39;,        &#39;Magento_Checkout/js/model/quote&#39;    ],    function ($,messageList,quote) {        &#39;use strict&#39;;        return {            /**             * Validate street not have po box             *             * @returns {boolean}             */            validate: function() {            var pass = false;            //在这里添加自己的一些验证代码            //验证不通过返回错误信息            messageList.addErrorMessage({message: &#39;show message!&#39; });            return pass;        }    } );

验证不通过的效果:

添加street内容更改时触发事件,借鉴postcode验证方式:

Magento_Checkout/js/model/shipping-rates-validator.js

/** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /** * @api */ define([    &#39;jquery&#39;,    &#39;ko&#39;,    &#39;Magento_Checkout/js/model/shipping-rates-validation-rules&#39;,    &#39;Magento_Checkout/js/model/address-converter&#39;,    &#39;Magento_Checkout/js/action/select-shipping-address&#39;,    &#39;Magento_Checkout/js/model/postcode-validator&#39;,    &#39;Magento_Checkout/js/model/default-validator&#39;,    &#39;mage/translate&#39;,    &#39;uiRegistry&#39;,    &#39;Magento_Checkout/js/model/shipping-address/form-popup-state&#39;,    &#39;Magento_Checkout/js/model/quote&#39; ], function (    $,    ko,    shippingRatesValidationRules,    addressConverter,    selectShippingAddress,    postcodeValidator,    defaultValidator,    $t,    uiRegistry,    formPopUpState ) {    &#39;use strict&#39;;    var checkoutConfig = window.checkoutConfig,        validators = [],        observedElements = [],        postcodeElement = null,        postcodeElementName = &#39;postcode&#39;,        streetElementName = &#39;street.0&#39;,//定义验证字段元素名称        streetElementFormName = &#39;street[0]&#39;,        streetElement = null;    validators.push(defaultValidator);    return {        validateAddressTimeout: 0,        validateDelay: 2000,        /**这个方法会注册各个shipping method插件的验证器,比如ups,free shipping tablerate等         * @param {String} carrier         * @param {Object} validator         */        registerValidator: function (carrier, validator) {        //checkoutConfig里面保存了很多配置信息,这里取的是已经开启的shipping method的名称;            if (checkoutConfig.activeCarriers.indexOf(carrier) !== -1) {            //注册shipping method提供的验证器,前提是该shipping method已经开启;                validators.push(validator);            }        },        /**验证数据         * @param {Object} address         * @return {Boolean}         */        validateAddressData: function (address) {            return validators.some(function (validator) {                return validator.validate(address);            });        },        /**         * 初始化字段,对应字段绑定事件         *         * @param {String} formPath         */        initFields: function (formPath) {            var self = this,            //elements通过shippingRatesValidationRules里面获取各个shipping method提供的rules返回的字段,我这里因为跟shipping method无关就直接把street插入进去了。                elements = shippingRatesValidationRules.getObservableFields();            if ($.inArray(postcodeElementName, elements) === -1) {                // Add postcode field to observables if not exist for zip code validation support                elements.push(postcodeElementName);            }            //在这里添加street字段            if ($.inArray(streetElementName, elements) === -1) {                // Add street field to observables if not exist                elements.push(streetElementName);            }            $.each(elements, function (index, field) {                uiRegistry.async(formPath + &#39;.&#39; + field)(self.doElementBinding.bind(self));            });        },        /**         * 将请求绑定到表单元素         *         * @param {Object} element         * @param {Boolean} force         * @param {Number} delay         */        doElementBinding: function (element, force, delay) {            var observableFields = shippingRatesValidationRules.getObservableFields();            if (element && (observableFields.indexOf(element.index) !== -1 || force)) {                if (element.index !== postcodeElementName) {                    this.bindHandler(element, delay);                }                //这里因为street是数组格式,index=0  所以我换了inputName方式判断,模拟postcode的处理方式                if (element.inputName !== streetElementFormName) {                    this.bindHandler(element, delay);                }            }            if (element.index === postcodeElementName) {                this.bindHandler(element, delay);                postcodeElement = element;            }            if (element.inputName === streetElementFormName) {                this.bindHandler(element, delay);                streetElement = element;            }        },        /**         * @param {*} elements         * @param {Boolean} force         * @param {Number} delay         */        bindChangeHandlers: function (elements, force, delay) {            var self = this;            $.each(elements, function (index, elem) {                self.doElementBinding(elem, force, delay);            });        },        /**         * @param {Object} element         * @param {Number} delay         */        bindHandler: function (element, delay) {            var self = this;            delay = typeof delay === &#39;undefined&#39; ? self.validateDelay : delay;            if (element.component.indexOf(&#39;/group&#39;) !== -1) {                $.each(element.elems(), function (index, elem) {                    self.bindHandler(elem);                });            } else {                element.on(&#39;value&#39;, function () {                    if (!formPopUpState.isVisible()) {                        clearTimeout(self.validateAddressTimeout);                        self.validateAddressTimeout = setTimeout(function () {                            self.postcodeValidation();                            self.validateFields();                            self.streetValidation();//模拟postcode验证,添加了自己的验证方法                        }, delay);                    }                });                observedElements.push(element);            }        },        streetValidation: function (){            streetElement.error(null);            //添加自定义验证内容            if(!pass){                streetElement.error(&#39;PLEASE NOTE: WE DO NOT SHIP TO P.O. BOXES!&#39;);            }            return pass;        },        /**         * @return {*}         */        postcodeValidation: function () {            var countryId = $(&#39;select[name="country_id"]&#39;).val(),                validationResult,                warnMessage;            if (postcodeElement == null || postcodeElement.value() == null) {                return true;            }            postcodeElement.warn(null);            validationResult = postcodeValidator.validate(postcodeElement.value(), countryId);            if (!validationResult) {                warnMessage = $t(&#39;Provided Zip/Postal Code seems to be invalid.&#39;);                if (postcodeValidator.validatedPostCodeExample.length) {                    warnMessage += $t(&#39; Example: &#39;) + postcodeValidator.validatedPostCodeExample.join(&#39;; &#39;) + &#39;. &#39;;                }                warnMessage += $t(&#39;If you believe it is the right one you can ignore this notice.&#39;);                postcodeElement.warn(warnMessage);            }            return validationResult;        },        /**         * Convert form data to quote address and validate fields for shipping rates         */        validateFields: function () {            var addressFlat = addressConverter.formDataProviderToFlatData(                this.collectObservedData(),                &#39;shippingAddress&#39;                ),                address;            if (this.validateAddressData(addressFlat)) {                addressFlat = uiRegistry.get(&#39;checkoutProvider&#39;).shippingAddress;                address = addressConverter.formAddressDataToQuoteAddress(addressFlat);                selectShippingAddress(address);            }        },        /**         * Collect observed fields data to object         *         * @returns {*}         */        collectObservedData: function () {            var observedValues = {};            $.each(observedElements, function (index, field) {                observedValues[field.dataScope] = field.value();            });            return observedValues;        }    }; });


内容更改就会触发验证:

最后:一定要注意位置和命名,遇到问题浏览器断点调试,熟悉处理流程以及对应数据变化,这里可能不是最好的和最规范的操作。如果有更好的方法,希望指出来改进改进。

0