9

How to add new rule to rules.js? I have created extra-rules.js

define(
[
    'jquery',
    'Magento_Ui/js/lib/validation/validator'
], function ($, validator) {
    "use strict";
    return validator.addRule('phoneNO',
        function (value) {
            return value.length > 9 && value.match(/^(\(?(0|\+44)[1-9]{1}\d{1,4}?\)?\s?\d{3,4}\s?\d{3,4})$/);
        },
        $.mage.__('Please specify a valid phone number')
    );
});

How to merge this rule to rules.js?

18

Here is a full and real working example to add a custom rule to checkout input field for checking minimum age:

Create a requirejs-config.js in your module to add a mixing to the validator object to Namespace/Modulename/view/frontend/requirejs-config.js with the following content:

var config = {
    config: {
        mixins: {
            'Magento_Ui/js/lib/validation/validator': {
                'Namespace_Modulename/js/validator-mixin': true
            }
        }
    }
};

Create a js script into your module folder into Namespace/Modulename/view/frontend/web/js/validator-mixin.js with the following content:

define([
    'jquery',
    'moment'
], function ($, moment) {
    'use strict';

    return function (validator) {

        validator.addRule(
            'validate-minimum-age',
            function (value, params, additionalParams) {
                return $.mage.isEmptyNoTrim(value) || moment(value, additionalParams.dateFormat).isBefore(moment().subtract(params.minimum_age, 'y'));
            },
            $.mage.__("Sorry, you don't have the age to purchase the current articles.")
        );

        return validator;
    };
});

USAGE

If you want to use a Magento PHP plugin to insert an input field into your checkout shipping address and validate the content of this field with the custom rule that you previously added, here is a sample code:

Create a di.xml file into the etc/frontend folder of your module with the following content:

<?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="CheckoutLayoutProcessor" type="Namespace\Modulename\Plugin\Block\Checkout\LayoutProcessor" />
    </type>
</config>

Then create the LayoutProcessor.php file into app/code/Namespace/Modulename/Plugin/Block/Checkout/LayoutProcessor.php with the following content, please update it for your needs:

<?php
/**
 * diglin GmbH - Switzerland
 *
 * @author      Sylvain Rayé <support **at** diglin.com>
 * @category    diglin
 * @package     diglin
 * @copyright   Copyright (c) diglin (http://www.diglin.com)
 */

namespace MyNamespace\Modulename\Plugin\Block\Checkout;

use MyNamespace\Modulename\Helper\AgeValidation;

/**
 * Class LayoutProcessor
 * @package MyNamespace\Modulename\Plugin\Block\Checkout
 */
class LayoutProcessor
{
    /**
     * @var \MyNamespace\Checkout\Helper\AgeValidation
     */
    private $ageValidation;
    /**
     * @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface
     */
    private $timezone;
    /**
     * @var \Magento\Framework\App\Config\ScopeConfigInterface
     */
    private $scopeConfig;

    /**
     * LayoutProcessor constructor.
     *
     * @param \MyNamespace\Checkout\Helper\AgeValidation $ageValidation
     * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $timezone
     * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
     */
    public function __construct(
        AgeValidation $ageValidation,
        \Magento\Framework\Stdlib\DateTime\TimezoneInterface $timezone,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
    )
    {
        $this->ageValidation = $ageValidation;
        $this->timezone = $timezone;
        $this->scopeConfig = $scopeConfig;
    }

    /**
     * Checkout LayoutProcessor after process plugin.
     *
     * @param \Magento\Checkout\Block\Checkout\LayoutProcessor $processor
     * @param array $jsLayout
     *
     * @return array
     */
    public function afterProcess(\Magento\Checkout\Block\Checkout\LayoutProcessor $processor, $jsLayout)
    {
        $shippingConfiguration = &$jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
        ['children']['shippingAddress']['children']['shipping-address-fieldset']['children'];

        // Checks if shipping step available.
        if (isset($shippingConfiguration)) {
            $shippingConfiguration = $this->processAddress(
                $shippingConfiguration
            );
        }

        return $jsLayout;
    }

    /**
     * Process provided address to contains checkbox and have trackable address fields.
     *
     * @param $addressFieldset - Address fieldset config.
     *
     * @return array
     */
    private function processAddress($addressFieldset)
    {
        $minimumAge = $this->ageValidation->getMinimumAge();
        if ($minimumAge === null) {
            unset($addressFieldset['my_dob']);
        } else {
            $addressFieldset['my_dob'] = array_merge(
                $addressFieldset['my_dob'],
                [
                    'component' => 'Magento_Ui/js/form/element/date',
                    'config' => array_merge(
                        $addressFieldset['my_dob']['config'],
                        [
                            'elementTmpl' => 'ui/form/element/date',
                            // options of datepicker - see http://api.jqueryui.com/datepicker/
                            'options' => [
                                'dateFormat' => $this->timezone->getDateFormatWithLongYear(),
                                'yearRange' => '-120y:c+nn',
                                'maxDate' => '-1d',
                                'changeMonth' => 'true',
                                'changeYear' => 'true',
                                'showOn' => 'both',
                                'firstDay' => $this->getFirstDay(),
                            ],
                        ]
                    ),
                    'validation' => array_merge($addressFieldset['my_dob']['validation'],
                        [
                            'required-entry' => true,
                            'validate-date' => true,
                            'validate-minimum-age' => $minimumAge, // custom value in year - array('minimum_age' => 16)
                        ]
                    ),
                ]
            );
        }

        return $addressFieldset;
    }

    /**
     * Return first day of the week
     *
     * @return int
     */
    public function getFirstDay()
    {
        return (int)$this->scopeConfig->getValue(
            'general/locale/firstday',
            \Magento\Store\Model\ScopeInterface::SCOPE_STORE
        );
    }
}

EDIT

Thanks @alan-storm for your explanation here https://alanstorm.com/the-curious-case-of-magento-2-mixins/ and @jisse-reitsma bring in the direction

Plus Magento 2 doc http://devdocs.magento.com/guides/v2.2/javascript-dev-guide/javascript/js_mixins.html

  • 1
    I get an error Loading failed for the <script> with source “.../validator-mixin.js" and Script error for: Namespace_Modulename/js/validator-mixin. – Jurģis Toms Liepiņš Feb 17 '18 at 20:17
  • 1
    validator-mixin.js location should be: /view/frontend/web/js/validator-mixin.js – Jurģis Toms Liepiņš Feb 18 '18 at 14:44
  • Doesn't work, Magento 2 just ignores this – cjohansson Sep 20 at 9:03
  • @cjohansson probably because it was done for a Magento 2.1 and 2.2 project. If you use 2.3, it's maybe not anymore possible. In our case it worked for the version I mentioned – Sylvain Rayé Oct 11 at 9:52
1

The original rules.js returns an object literal, containing all rules. You can modify this object literal by adding a mixin to this file. The Magento docs give some guidance on how to do this: Magento Javascript Mixins

0

The same issue was answered here: Magento 2 add custom validation rule

A really good source for understanding this system is here: https://alanstorm.com/the-curious-case-of-magento-2-mixins/

And not exactly what you are trying to do, but a very good source here: https://www.youtube.com/watch?v=0fguDL5iEd0&t=540s

0

It working for me:

Create a requirejs-config.js in your module to add a mixing to the validator object to app/design/frontend/Vendor/Theme/Magento_Ui/requirejs-config.js with the following content:

var config = {
    config: {
        mixins: {
            'Magento_Ui/js/lib/validation/rules': {
                'Magento_Ui/js/lib/validation/rules-mixin': true
            }
        }
    }
};

Create a js script into your module folder into app/design/frontend/Vendor/Theme/Magento_Ui/web/js/lib/validation/rules-mixin.js with the following content:

define([
    'jquery',
    'underscore',
    'moment',
    'mage/translate'
], function ($, _, moment) {
    'use strict';

    return function (validator) {
        var validators = {
            'letters-spaces-only': [
                function (value) {
                    return /^[a-zA-Z ]*$/i.test(value);
                },
                $.mage.__('Only letters and spaces.')
            ]
        };

        validators = _.mapObject(validators, function (data) {
            return {
                handler: data[0],
                message: data[1]
            };
        });

        return $.extend(validator, validators);
    };
});

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.