3

I have added a custom field in checkout called "Area". Area field is required by default, but I'd like to change that based on the selected country.

If customer selects a country other than FR, then Area field should become optional (not required).

Can you help me do that?

require([
    "jquery",
    "jquery/ui",
    "domReady!"
],
function($) {
    function load() {

        var country_select = $('div#shipping-new-address-form>div[name="shippingAddress.country_id"]>div.control>select.select');

        country_select.change(function () {
            var selected_country = $('div#shipping-new-address-form>div[name="shippingAddress.country_id"]>div.control>select.select :selected').val();

            if(selected_country == 'FR'){
                // make Area field required
            }else{
                // make Area field optional
            }

        });
    }
});

4 Answers 4

2

Add 'validation' index in layout processor for your custom field as

'validate-area-required' => true,

And add your mixin validation-mixin.js with

define([
    'jquery',
    'Magento_Ui/js/lib/validation/utils'
], function ($, utils) {
    "use strict";

    return function (validator) {            
        validator.addRule(
            'validate-area-required',
            function (value) {
                var selected_country = $('div#shipping-new-address-form>div[name="shippingAddress.country_id"]>div.control>select.select :selected').val();
                if(selected_country == 'FR'){
                    return true;
                }else{
                    return false;
                }

            },
            $.mage.__('Required field.')
        );
        return validator;
    }
});

Not tested...Hope it will work!

12
  • I don't understand how this code is related to Area field. Where should this be placed: 'validate-area-required' => true,?
    – zekia
    Sep 30, 2019 at 12:41
  • Do you aware of validation rule classes like required-entity etc?. Sep 30, 2019 at 12:52
  • You need to add this in your layoutprocessor....Which you used to create a new custom field Sep 30, 2019 at 12:55
  • Ok I managed to test this code, after searching other validation related issues. But it's not working... It's not toggling requirement on field, but just displays 'Required field.' after changing it, whatever selected_country is.
    – zekia
    Oct 3, 2019 at 6:42
  • 1
    Try with updated answer Oct 3, 2019 at 7:18
2
+25

Use the below code for country wise validation. It will check every time when you proceed to payment step
Or you can empty value every time after the country change.

define([
    'jquery',
    'Magento_Ui/js/lib/validation/utils'
], function ($, utils) {
    "use strict";

    return function (validator) {            
        validator.addRule(
            'validate-area-required',
            function (value) { 
                var country = $("#co-shipping-form [name='country_id']").val() || $(".modal-popup [name='country_id']").val()
                if(country=='FR'){
                    return !utils.isEmpty(value);
                }else{
                    return true;
                }
            },
            $.mage.__('Required field.')
        );
        return validator;
    }
});
1

Read your code。 You are not using Knockoutjs, if it is just normal validation behavior, then:

Add the disabled attribute to the select control using jquery's attr method.

Hope can help you。

0

In di.xml

<type name="Magento\Checkout\Block\Onepage">
    <arguments>
        <argument name="layoutProcessors" xsi:type="array">
        <item name="unique_name" xsi:type="object">[Vendor]\[Modulue]\Block\Checkout\LayoutProcessor</item>
        </argument>
    </arguments>
</type>

[Vendor][Modulue]\Block\Checkout\LayoutProcessor.php file

<?php
namespace [Vendor]\[Modulue]\Block\Checkout;


class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcessorInterface
{
    /**
     * @param array $result
     * @return array
     */
    public function process($result)
    {
    $configuration = isset($result['components']['checkout']['children']['steps']
    ['children']['billing-step']['children']['payment']['children']['payments-list']['children'])
        ? $result['components']['checkout']['children']['steps']
            ['children']['billing-step']['children']['payment']['children']['payments-list']['children'] :'';
    if ($configuration) {
        foreach ($configuration as $paymentGroup => $groupConfig) {

            if (isset($groupConfig['component']) &&
                    $groupConfig['component'] === 'Magento_Checkout/js/view/billing-address') {
                $result['components']['checkout']['children']['steps']['children']['billing-step']['children']
                ['payment']['children']['payments-list']['children'][$paymentGroup]['children']['form-fields']
                ['children']['company_tax_id'] = [
                    'component' => 'Magento_Ui/js/form/element/abstract',
                    'config' => [
                        'customScope' => ''.$groupConfig['dataScopePrefix'].'.custom_attributes',
                        'template' => 'ui/form/field',
                        'elementTmpl' => 'ui/form/element/input',
                        'options' => [],

                    ],
                    'dataScope' => ''.$groupConfig['dataScopePrefix'].'.custom_attributes.state', // your name here in my case state
                    'label' => 'Other State',
                    'provider' => 'checkoutProvider',
                    'visible' => true,
                    'validation' => ['custom-state' => true], // your new validation name here in my case custom-state
                    'sortOrder' => 105,
                ];
            }
        }
    }
    return $result;
    }
}

[Vendor]/[Modulue]/view/frontend/requirejs-config.js

var config = {
    config: {
    mixins: {
         'Magento_Checkout/js/action/place-order': {
            '[Vendor]_[Modulue]/js/action/place-order-mixin': true
        },
    }
    }
};

[Vendor]/[Modulue]/view/frontend/web/js/action

/*jshint browser:true jquery:true*/
/*global alert*/
define([
    'jquery',
    'mage/utils/wrapper',
    'Magento_Checkout/js/model/quote',
    'Magento_Ui/js/lib/validation/validator'
], function ($, wrapper, quote,validator) {
    'use strict';
    validator.addRule(
    'custom-state',
    function (value) {
       // Your Condition return true false based on condition       
        if ($('.payment-method._active [name="custom_attributes[state]"]').length > 0 ) {
            if ($('.payment-method._active [name="custom_attributes[state]"]').is(':visible') && $('.payment-method._active [name="custom_attributes[state]"]').val() == ''){
                return false;
            } else {
                return true;
            }
        }

    },
    $.mage.__('This is a required field.')
    );

    return function (placeOrderAction) {

    /** Override default place order action and add agreement_ids to request */
    return wrapper.wrap(placeOrderAction, function (originalAction, paymentData, messageContainer) {
        var billingAddress = quote.billingAddress();
        if (billingAddress['extension_attributes'] === undefined) {
            billingAddress['extension_attributes'] = {};
        }
        billingAddress['extension_attributes']['state'] = $('.payment-method._active [name="custom_attributes[state]"]').val();
        return originalAction(paymentData, messageContainer);
    });
    };
});
3
  • I don't understand how your code is related to the area/country example I mentioned in my question. My question is about triggering a field's validation by changing another field.
    – zekia
    Oct 15, 2019 at 12:13
  • @zekia, you can check country check via jquery and you can add additional class in your feild and you can validate based on it Oct 15, 2019 at 12:21
  • Your answer is about adding custom validation to field. I have already done that, but I'm missing the part where changing one field triggers validation on another field. Can you help me with that?
    – zekia
    Oct 15, 2019 at 12:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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