0

I'm trying to create a mask for telephone field in Magento 2.2.2 checkout. In order to do so. I placed a checkout_index_index.xml with a new template for telephone field at

vendor/mytheme/Magento_Checkout/layout/checkout_index_index.xml

    <?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="checkout.root">
            <arguments>
                <argument name="jsLayout" xsi:type="array">
                    <item name="components" xsi:type="array">
                        <item name="checkout" xsi:type="array">
                            <item name="children" xsi:type="array">
                                <item name="steps" xsi:type="array">
                                    <item name="children" xsi:type="array">
                                        <item name="shipping-step" xsi:type="array">
                                            <item name="children" xsi:type="array">
                                                <item name="shippingAddress" xsi:type="array">
                                                    <item name="children" xsi:type="array">
                                                        <!-- The name of the form the field belongs to -->
                                                        <item name="shipping-address-fieldset" xsi:type="array">
                                                            <item name="children" xsi:type="array">
                                                                <!-- the field you are customizing -->
                                                                <item name="telephone" xsi:type="array">
                                                                    <item name="component" xsi:type="string">Magento_Checkout/js/view/masked</item>
                                                                    <item name="config" xsi:type="array">
                                                                        <!-- Assigning a new template -->

                                                                        <item name="elementTmpl" xsi:type="string">Magento_Checkout/form/element/telefone</item>

                                                                    </item>
                                                                </item>
                                                            </item>
                                                        </item>
                                                    </item>
                                                </item>
                                            </item>
                                        </item>
                                    </item>
                                </item>
                            </item>
                        </item>
                    </item>
                </argument>
            </arguments>
        </referenceBlock>
    </body>
</page>

In the folder vendor/mytheme/web/js/view/masked.js I place bellow code

define(['jquery', 'uiComponent', 'ko', ], function ( $, Component, ko) {
        'use strict';
         return Component.extend({
             defaults: {
                template: 'Magento_Checkout/telefone'
            },
            initialize: function () {
                var self = this;
                this._super();
                ko.bindingHandlers.maskedInput = {
                    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
                    ko.bindingHandlers.value.init(element, valueAccessor, allBindings, viewModel, bindingContext);
                    },
                    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
                        ko.bindingHandlers.value.update(element, valueAccessor, allBindings, viewModel, bindingContext);
                        $(element).mask(allBindings.get('mask'));
                        valueAccessor()($(element).val());
                    }
                };

                var ViewModel = function() {

                    this.phone = ko.observable("");


                    this.phone('123123451212');
                }; 
                ko.applyBindings(new ViewModel());
        }

    }       
)
}
);

And the I created template telefone.html at vendor/mytheme/Magento_Checkout/web/template

<input class="input-text" type="text" data-bind="
    value: value,
    valueUpdate: 'keyup',
    maskedInput: phone, 
    mask: '(999) 999-9999',
    hasFocus: focused,
    attr: {
        name: inputName,
        placeholder: placeholder,
        'aria-describedby': noticeId,
        id: uid,
        disabled: disabled
    }" />

But when I go to checkout I get error: Uncaught Error: You cannot apply bindings multiple times to the same element. Does someone know a proper way to apply phone mask to telephone input at checkout. Or, if my method is correct, what am I missing or doing wrong?

  • When you use component there is no need to applyBindings on it.It will do it automatically – Zaheerabbas Apr 13 '18 at 14:04
  • I removed " ko.applyBindings(new ViewModel());" and now I get ReferenceError: Unable to process binding "css: function (){return additionalClasses }" Message: Can't find variable: additionalClasses – Gabriela Apr 13 '18 at 14:54
  • @Gabriela, Have you got any solution for this? – Pushpendra Singh Jun 22 '18 at 9:48
  • Sorry, I didn't find a solution. If you have any, please post it here. – Gabriela Jun 29 '18 at 13:05
0

There is seems to be a conflict because below layout you have already mentioned the template of element and re-defined the template in your component js file also,

vendor/mytheme/Magento_Checkout/layout/checkout_index_index.xml

<!-- the field you are customizing -->
<item name="telephone" xsi:type="array">
    <item name="component" xsi:type="string">Magento_Checkout/js/view/masked</item>
        <item name="config" xsi:type="array">
        <!-- Assigning a new template -->
        <item name="elementTmpl" xsi:type="string">Magento_Checkout/form/element/telefone</item>
    </item>
</item>

Hence try replace below component script with your, vendor/mytheme/web/js/view/masked.js

define([
    'underscore', 'ko',
    'mageUtils',    
    'Magento_Ui/js/form/element/abstract',
    'uiLayout'
], function (_, ko, utils, Abstract, layout) {
    'use strict';

    return Abstract.extend({
        initialize: function () {
            this._super();

            //add your custom code or call custom functions
            ko.bindingHandlers.maskedInput = {
                init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
                ko.bindingHandlers.value.init(element, valueAccessor, allBindings, viewModel, bindingContext);
                },
                update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
                    ko.bindingHandlers.value.update(element, valueAccessor, allBindings, viewModel, bindingContext);
                    $(element).mask(allBindings.get('mask'));
                    valueAccessor()($(element).val());
                }
            };

            var ViewModel = function() {
                this.phone = ko.observable("");
                this.phone('123123451212');
            }; 
            ko.applyBindings(new ViewModel());

            return this;
        }            
    });
});

Note : script extends from Magento_Ui/js/form/element/abstract

  • Didn't work either – Gabriela Oct 8 '18 at 17:23
0

My goal is just to put a mask for the telephone field in Magento2 Checkout. Since the Knockout method didn't work I simple declared a new template in checkout_index_index.xml with the bellow code:

        <input class="input-text" type="text"  placeholder= (__)_____-____ data-bind="
            value: value,
            valueUpdate: 'keyup',
            attr: {
                name: inputName,       
                id: uid
            }" name="telephone" aria-required="true" aria-invalid="false" autocomplete="off" onfocus="this.value='(';" onkeyup="var telephone = this.value;                                                                                 
           if (telephone.match(/^\(\d{2}$/) !==null) {
             this.value = telephone + ')';
          } else if (telephone.match(/^\(\d{2}\)\d{5}$/) !== null) {
             this.value = telephone + '-';
          }" maxlength="14"/>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.