Magento 2 – Add Custom Required Field Validation on Checkout Page

checkoutmagento2

I am using this extension to add custom field on checkout page.

Using this solution i have added my custom dropdown field in checkout.

All working fine till now.

Now i want to add required validation for my custom field. But i am not getting how to add.

enter image description here

If someone select Free shipping, Refer By option should be required and for other shipping method it should be optional.

Update: Here is the code that i am using to display dropdown

view\frontend\web\template\delivery-date-block.html

<label class="label">Delivery Date</label>
<div class="control">
    <input class="input-text" type="text" data-bind="datetimepicker: true"  name="delivery_date" id="delivery_date" readonly="true"/>
</div>
<br/>
<label class="label">Comment</label>
<div class="control">
    <textarea name="delivery_comment" id="delivery_comment"></textarea>
</div>
<br/>
<br/>
<label class="label">Refer By</label>
<div class="control">

    <select name="refer_by" id="refer_by"
            class="input-select"
            data-bind="
                                  options: getCustomOption(),
                                  optionsValue: 'value',
                                  optionsText: 'label',
                                  optionsCaption: $t('---Select Store---'),
                                  value: customOptionValue">
    </select>
</div>

view\frontend\web\js\model\shipping-save-processor\default.js

/*global define,alert*/
define(
    [
        'jquery',
        'ko',
        'Magento_Checkout/js/model/quote',
        'Magento_Checkout/js/model/resource-url-manager',
        'mage/storage',
        'Magento_Checkout/js/model/payment-service',
        'Magento_Checkout/js/model/payment/method-converter',
        'Magento_Checkout/js/model/error-processor',
        'Magento_Checkout/js/model/full-screen-loader',
        'Magento_Checkout/js/action/select-billing-address'
    ],
    function (
        $,
        ko,
        quote,
        resourceUrlManager,
        storage,
        paymentService,
        methodConverter,
        errorProcessor,
        fullScreenLoader,
        selectBillingAddressAction
    ) {
        'use strict';

        return {
            saveShippingInformation: function () {
                var payload;

                if (!quote.billingAddress()) {
                    selectBillingAddressAction(quote.shippingAddress());
                }

                payload = {
                    addressInformation: {
                        shipping_address: quote.shippingAddress(),
                        billing_address: quote.billingAddress(),
                        shipping_method_code: quote.shippingMethod().method_code,
                        shipping_carrier_code: quote.shippingMethod().carrier_code,
                        extension_attributes:{
                            delivery_date: $('[name="delivery_date"]').val(),
                            delivery_comment: $('[name="delivery_comment"]').val(),
                            store_pickup: $('[name="store_pickup"]').val(),
                        }
                    }
                };

                fullScreenLoader.startLoader();

                return storage.post(
                    resourceUrlManager.getUrlForSetShippingInformation(quote),
                    JSON.stringify(payload)
                ).done(
                    function (response) {
                        quote.setTotals(response.totals);
                        paymentService.setPaymentMethods(methodConverter(response.payment_methods));
                        fullScreenLoader.stopLoader();
                    }
                ).fail(
                    function (response) {
                        errorProcessor.process(response);
                        fullScreenLoader.stopLoader();
                    }
                );
            }
        };
    }
);

view\frontend\web\js\view\delivery-date-block.js

define([
    'jquery',
    'ko',
    'uiComponent'
], function ($, ko, Component) {
    'use strict';

    return Component.extend({
        defaults: {
            template: 'SR_DeliveryDate/delivery-date-block',
            customOptionValue: ''
        },
        initialize: function () {
            this._super();
            var disabled = window.checkoutConfig.shipping.delivery_date.disabled;
            var noday = window.checkoutConfig.shipping.delivery_date.noday;
            var hourMin = parseInt(window.checkoutConfig.shipping.delivery_date.hourMin);
            var hourMax = parseInt(window.checkoutConfig.shipping.delivery_date.hourMax);
            var format = window.checkoutConfig.shipping.delivery_date.format;
            if(!format) {
                format = 'yy-mm-dd';
            }
            var disabledDay = disabled.split(",").map(function(item) {
                return parseInt(item, 10);
            });

            ko.bindingHandlers.datetimepicker = {
                init: function (element, valueAccessor, allBindingsAccessor) {
                    var $el = $(element);
                    //initialize datetimepicker
                    if(noday) {
                        var options = {
                            minDate: 0,
                            dateFormat:format,
                            hourMin: hourMin,
                            hourMax: hourMax
                        };
                    } else {
                        var options = {
                            minDate: 0,
                            dateFormat:format,
                            hourMin: hourMin,
                            hourMax: hourMax,
                            beforeShowDay: function(date) {
                                var day = date.getDay();
                                if(disabledDay.indexOf(day) > -1) {
                                    return [false];
                                } else {
                                    return [true];
                                }
                            }
                        };
                    }

                    $el.datetimepicker(options);

                    var writable = valueAccessor();
                    if (!ko.isObservable(writable)) {
                        var propWriters = allBindingsAccessor()._ko_property_writers;
                        if (propWriters && propWriters.datetimepicker) {
                            writable = propWriters.datetimepicker;
                        } else {
                            return;
                        }
                    }
                    writable($(element).datetimepicker("getDate"));
                },
                update: function (element, valueAccessor) {
                    var widget = $(element).data("DateTimePicker");
                    //when the view model is updated, update the widget
                    if (widget) {
                        var date = ko.utils.unwrapObservable(valueAccessor());
                        widget.date(date);
                    }
                }
            };

            return this;
        },
        initObservable: function () {

            this._super()
                .observe([
                    'customOptionValue'
                ]);
            return this;
        },
        getCustomOption: function() {
            return _.map(window.checkoutConfig.shipping.delivery_date.customOptionValue, function(value, key) {
                return {
                    'value': key,
                    'label': value
                }
            });
        }
    });
});

Best Answer

Modify app/code/SR/DeliveryDate/view/frontend/requirejs-config.js


var config = {
    "map": {
        "*": {
            'Magento_Checkout/js/model/shipping-save-processor/default': 'SR_DeliveryDate/js/model/shipping-save-processor/default'
        }
    },
    config: {
        mixins: {
            'Magento_Checkout/js/view/shipping': {
                'SR_DeliveryDate/js/mixin/shipping-mixin': true
            }
        }
    }
};

app/code/SR/DeliveryDate/view/frontend/web/js/mixin/shipping-mixin.js


define([
    'jquery',
    'Magento_Checkout/js/model/quote'
], function ($, quote) {
    'use strict';

    return function (target) {
        return target.extend({

            /**
             * Set shipping information handler
             */
            setShippingInformation: function () {
                var shippingMethod = quote.shippingMethod();
                if (shippingMethod['method_code'] == 'freeshipping') {
                    if ($("#custom_option").val() == '') {
                        this.focusInvalid();
                        return false;
                    }
                }
                this._super();
            }
        });
    }
});
Related Topic