How to Set Radio Buttons in Custom Payment Method as Required in Magento 2

checkoutknockoutjsmagento2payment-methodsradio-fields

So, I have set up a payment method (Leasing) – when chosen, you have the choice between different leasing providers. It is working so far, as the providers are shown in the checkout, I can click them and "order".

But I failed to make those radio buttons to be required entries.

I used this tutorial to make a text field required:
https://webkul.com/blog/how-to-add-custom-field-for-a-payment-method-in-magento2/
and tried to work from there.

But tbh. I still dont really know, what I am doing wrong and knockout gives me headaches xD

Here is my template:

<div class="payment-method payment-method-leasing" data-bind="css: {'_active': (getCode() == isChecked())}">
    <div class="payment-method-title field choice">
        <input type="radio"
               name="payment[method]"
               class="radio"
               data-bind="attr: {'id': getCode()}, value: getCode(), checked: isChecked, click: selectPaymentMethod, visible: isRadioButtonVisible()"/>
        <label data-bind="attr: {'for': getCode()}" class="label">
            <img data-bind="attr: {'src': logo, 'alt': $t('Payment Method Logo')}" class="leasing-logo payment-method-logo" />
            <span data-bind="text: getTitle()"></span>
        </label>
    </div>

    <div class="payment-method-content">
        <!-- ko foreach: getRegion('messages') -->
        <!-- ko template: getTemplate() --><!-- /ko -->
        <!--/ko-->
        <div class="payment-method-billing-address">
            <!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) -->
            <!-- ko template: getTemplate() --><!-- /ko -->
            <!--/ko-->
        </div>
        <form id="leasing_form" class="form form-leasing" data-role="leasing_form">
            <fieldset class="fieldset payment method" data-bind='attr: {id: "payment_form_" + getCode()}'>

                <div class="field required">
                    <div class="control">
                        <div id="leasing-provider" class="leasing-provider-radio" data-bind="foreach: leasingProviders">
                            <input type="radio"
                            data-validate="{required:true}"
                            class="leasing-provider-radio-input"
                            data-bind="attr: {id: 'leasing-provider-' + value, name: 'payment[leasing-provider]', value: value}" />
                            <label data-bind="attr: {for: 'leasing-provider-' + value}">
                                <img data-bind="attr: {src: imgUrl, alt: label}" class="leasing-provider-image" />
                                <span data-bind="text: label"></span><br>
                            </label>
                        </div>
                    </div>

                </div>
            </fieldset>
        </form>
        <div class="checkout-agreements-block">
            <!-- ko foreach: $parent.getRegion('before-place-order') -->
                <!-- ko template: getTemplate() --><!-- /ko -->
            <!--/ko-->
        </div>
        <div class="actions-toolbar" id="review-buttons-container">
            <div class="primary">
                <button class="action primary checkout"
                        type="submit"
                        data-bind="
                        click: placeOrder,
                        attr: {title: $t('Place Order')},
                        enable: (getCode() == isChecked()),
                        css: {disabled: !isPlaceOrderActionAllowed()}
                        "
                        data-role="review-save">
                    <span data-bind="i18n: 'Place Order'"></span>
                </button>
            </div>
        </div>
    </div>
</div>

and here is the method-renderer js-file:

define(
    [
        'jquery',
        'Magento_Checkout/js/view/payment/default',
        'mage/url',
        'Magento_Checkout/js/model/error-processor',
        'Magento_Checkout/js/action/redirect-on-success',
        'Magento_Checkout/js/model/quote',
        'mage/validation'
    ],
    function ($,Component,url, errorProcessor,redirectOnSuccessAction, quote) {
        'use strict';

        return Component.extend({
            defaults: {
                template: 'Myvendor_LeasingPayment/payment/leasingtemplate',
                leasing: '',
                logo: "",
                leasingProviders: ""
            },
            /** @inheritdoc */
            initObservable: function () {
                this._super()
                    .observe(['leasing']);
                this.loadLeasingProviders();
                this.loadLogo();
                return this;
            },
            /**
         * @return {Object}
         */
        getData: function () {
            return {
                method: this.item.method,
                // 'mpesanumber': this.mpesaNumber(),
                'additional_data': {
                    'leasing': $("input.leasing-provider-radio-input:checked").val()
                }
            };
        },
        /**
         * @return {jQuery}
         */
        validate: function () {
            var form = 'form[data-role=leasing_form]';

            return $(form).validation() && $(form).validation('isValid');
        },

        loadLeasingProviders: function () {
            // Make an Ajax call to your backend to get the leasing providers
            $.ajax({
                url: '/myvendor_leasingpayment/payment/leasingProviders', // Replace with your actual backend URL
                method: 'GET',
                dataType: 'json',
                success: function (data) {
                    // Update the leasingProviders array with the received data
                    // console.log(data);
                    this.leasingProviders = data;
                }.bind(this),
                error: function () {
                    // Handle error
                }
            });
        },

        loadLogo: function () {
            // Make an Ajax call to your backend to get the leasing providers
            $.ajax({
                url: '/myvendor_leasingpayment/payment/Logo', // Replace with your actual backend URL
                method: 'GET',
                dataType: 'json',
                success: function (data) {
                    // Update the leasingProviders array with the received data
                    console.log(data);
                    this.logo = data.url;
                }.bind(this),
                error: function () {
                    // Handle error
                }
            });
        },

        });
    }
);

Best Answer

You have to added this code into page load event.

YOUR_RADIO_BUTTON_NAME: ko.observable().extend({
                    required: true
       }),

where YOUR_RADIO_BUTTON_NAME replace with your real radio button name.

Related Topic