13

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.

20

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.

4

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)

8
  • this makes sense, but how do I include my js validator in the page? Or where should I put my validation js? It's not like I can use <script scr="" somewhere in the page.
    – Marius
    Oct 7 '16 at 5:35
  • @Marius can't you just include the JS in your page ? I mean create a JS file and include it in the head ? Oct 7 '16 at 7:34
  • hmm...shouldn't that be done somehow via require js, when using my component? I don't know. I will try that, but it feels somehow dirty. Because for example the default validation js file is not included in the head. Only require.js and requirejs-config.
    – Marius
    Oct 7 '16 at 7:37
  • @Marius yeah I probably talked too fast. Still not used to all those require stuff Oct 7 '16 at 7:40
  • 2
    I think I found something but nor sure. Using $.validator.addMethod may work only for forms that are not built via ui components. Fo ui-components the validation is done via https://github.com/magento/magento2/blob/2.1/app/code/Magento/Ui/view/base/web/js/lib/validation/validator.js that uses https://github.com/magento/magento2/blob/2.1/app/code/Magento/Ui/view/base/web/js/lib/validation/rules.js. I think I need to find a way to extend this.
    – Marius
    Oct 7 '16 at 8:35
0

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!

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.