Question

I'm trying to have a custom validation to one of my Magento 2 form fields that is generated via ui-components.
I know that I can make the value required by adding a validation item in the config.
Like this:

   <field name="title">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="dataType" xsi:type="string">text</item>
                <item name="label" xsi:type="string" translate="true">Some label here</item>
                <item name="formElement" xsi:type="string">input</item>
                <item name="source" xsi:type="string">whatever</item>
                <item name="sortOrder" xsi:type="number">999</item>
                <item name="dataScope" xsi:type="string">whatever</item>
                <item name="validation" xsi:type="array">
                    <item name="required-entry" xsi:type="boolean">true</item><!-- this validates it as required -->
                </item>
            </item>
        </argument>
    </field>

What do I need to add inside the validation item and where do I place the js code that should validate my field based on custom conditions?
For example I want it to match a certain regex.

Was it helpful?

Solution

Basically I was able to find the answer to this from the last comment that Marius gave.

As he said the validation for forms generated by or with the help of the ui component are validated by the /Magent‌​o/Ui/view/base/web/j‌​s/lib/validation/val‌​idator.js 'module'. Now this module has anaddRule() function that is exactly what we need.

After adding the custom validation in the xml of your form:

<field name="title">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="dataType" xsi:type="string">text</item>
                <item name="label" xsi:type="string" translate="true">Some label here</item>
                <item name="formElement" xsi:type="string">input</item>
                <item name="source" xsi:type="string">whatever</item>
                <item name="sortOrder" xsi:type="number">999</item>
                <item name="dataScope" xsi:type="string">whatever</item>
                <item name="validation" xsi:type="array">
                    <item name="custom-validation" xsi:type="boolean">true</item>
                </item>
            </item>
        </argument>
    </field>

We must make a script that requires this 'module' and with the help of the addRule will add our custom validation:

[Namspace]/[Module]/view/[area]/web/js/our_custom_validation.js

   require(
        [
            'Magento_Ui/js/lib/validation/validator',
            'jquery',
            'mage/translate'
    ], function(validator, $){

            validator.addRule(
                'custom-validation',
                function (value) {
                    //return true or false based on your logic

                }
                ,$.mage.__('Custom Validation message.')
            );
});

Now this is not enough. We must include this file on the page that holds the form we want to validate.

We do so in the following manner: Let's say we want to add this to the customer_index_edit the [area] about will be [adminhtml] and we add the following file: [Namespace]/[Module]/view/adminhtml/layout/customer_index_edit.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <head>
        <link src="Namespace_Module::js/our_custom_validation.js"/>
    </head>
</page>

Do not forget to clean your cache deploy static content.

Hope this helps.

OTHER TIPS

From what I understood

So you can add your custom validation like this:

<item name="validation" xsi:type="array">
    <item name="required-entry" xsi:type="boolean">true</item>
    <item name="validate-regexp" xsi:type="string">REGEXP</item>
</item>

So here REGEXP needs to be a regular expression.

Then you will have to declare your own custom validation script to be able to handle validate-regexp

require([
'jquery', // jquery Library
'jquery/ui', // Jquery UI Library
'jquery/validate', // Jquery Validation Library
'mage/translate' // Magento text translate (Validation message translte as per language)
], function($){ 
$.validator.addMethod(
'validate-regexp', function (value, params) { 
return value.test(params); // Validation logic here
}, $.mage.__('Enter Valid Field'));

});

NB: it may be params.test(value) instead of value.test(params)

As @Marius said, the uicomponent created forms are a little bit different to all the documented custom validation examples.

Found a way to make sure the custom validation works with UI Components by extending the validation rules class

// view/{area}/requirejs-config.js
var config = {
    config: {
        mixins: {
            'Magento_Ui/js/lib/validation/rules': {
                'StackOverflow_Example/js/validation/rules-mixin': true
            }
        }
    }
}

Then in the mixin you define your validation rule as an addition to the returned rules object

// view/{area}/web/js/validation/rules-mixin.js
define([
    'mage/translate'
], function($t) {
    'use strict';
    return function (target) {
        target['custom-validation'] = {
            message: $t('Custom validation message will be translated. YEW'),
            handler: function (value) {
                return /stackOverflow/.test(value);
            }
        };
        return target;
    };
});

The example will validate any field with a validation added to ensure "stackOverflow" is written.

Just as a bonus, to add custom validation to a field in the Product Form ui component for example

<!-- etc/adminhtml/di.xml -->
    <virtualType name="Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Pool" type="Magento\Ui\DataProvider\Modifier\Pool">
        <arguments>
            <argument name="modifiers" xsi:type="array">
                <item name="stackoverflow_validation" xsi:type="array">
                    <item name="class" xsi:type="string">StackOverflow\Example\Ui\DataProvider\Product\Form\Modifier\Validation</item>
                    <item name="sortOrder" xsi:type="number">999</item>
                </item>
            </argument>
        </arguments>
    </virtualType>

With the modify meta basic example

// Ui/DataProvider/Product/Form/Modifier/Validation.php
class Validation implements \Magento\Ui\DataProvider\Modifier\ModifierInterface
{

    /**
     * @param array $data
     *
     * @return array
     */
    public function modifyData(array $data)
    {
        return $data;
    }

    /**
     * Add stackoverflow speicifc product validation
     *
     * @param array $meta
     *
     * @return array
     */
    public function modifyMeta(array $meta)
    {
        $meta['product-details']['children']['container_<attribute>']['children']['<attribute>']['arguments']['data']['config']['validation']['validate-sku'] = true;
        return $meta;
    }
}

Then run your handy dandy

   bin/magento setup:di:compile
   bin/magento setup:static-content:deploy
   bin/magento cache:clean

And you should be good to see the modified ui component validation!

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top