3

I am looking to create a custom checkbox field on the checkout process that a customer can click to define if they are a business customer or a consumer.

To do so I made a module with the file SomeProcessor.php:

    <?php
namespace BusinessCheckout\CustomCheckout\Block\Checkout;

class SomeProcessor
{
    /**
     * @param \Magento\Checkout\Block\Checkout\LayoutProcessor $subject
     * @param array $jsLayout
     * @return array
     */
    public function afterProcess(
        \Magento\Checkout\Block\Checkout\LayoutProcessor $subject,
        array  $jsLayout
    ) {

        $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']
        ['shippingAddress']['children']['shipping-address-fieldset']['children']['custom_checkbox'] = [
            'component' => 'Magento_Ui/js/form/element/abstract',
            'config' => [
                'customScope' => '.custom_checkbox',
                'template' => 'ui/form/field',
                'elementTmpl' => 'ui/form/element/checkbox',
                'options' => [],
                'id' => 'custom-field'
            ],
            'dataScope' => '.custom_checkbox',
            'label' => 'Is this a business order? Business T&C\'s apply.',
            'provider' => 'checkoutProvider',
            'visible' => true,
            'validation' => [],
            'sortOrder' => 50,
            'id' => 'custom-field'
        ];


        return $jsLayout;
    }
}
?>

All good so far and the checkbox appears on the checkout page as expected.

Now I've added the following jQuery to the footer of the site:

<script type="text/javascript">

jQuery(document).ready(function() {

  jQuery('form input[name="custom_checkbox"]').attr('checked', false)
  jQuery('form input[name="company"]').prop("disabled", true);

  jQuery('form input[name="custom_checkbox"]').click(function() {

    if (jQuery(this).prop("checked") == true) {

      jQuery('form input[name="company"]').prop("disabled", false);

    } else if (jQuery(this).prop("checked") == false) {

      jQuery('form input[name="company"]').prop("disabled", true);

    }

  });

});

</script>

It seems working when I enter it directly into console but not on the site footer.

The expected functionality is to have the checkbox unchecked when the page loads and the company field disabled. Then if the user clicks the checkbox the company field becomes enabled.

Any thoughts on how I can get this working?

8 Answers 8

5
+50

Try this:

I have updated your code from 'component' => 'Magento_Ui/js/form/element/abstract', To 'component' => 'BusinessCheckout_CustomCheckout/js/form/element/customCheckbox',.

    <?php
namespace BusinessCheckout\CustomCheckout\Block\Checkout;

class SomeProcessor
{
    /**
     * @param \Magento\Checkout\Block\Checkout\LayoutProcessor $subject
     * @param array $jsLayout
     * @return array
     */
    public function afterProcess(
        \Magento\Checkout\Block\Checkout\LayoutProcessor $subject,
        array  $jsLayout
    ) {

        $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']
        ['shippingAddress']['children']['shipping-address-fieldset']['children']['custom_checkbox'] = [
             'component' => 'BusinessCheckout_CustomCheckout/js/form/element/customCheckbox',
            'config' => [
                'customScope' => '.custom_checkbox',
                'template' => 'ui/form/field',
                'elementTmpl' => 'ui/form/element/checkbox',
                'options' => [],
                'id' => 'custom-field'
            ],
            'dataScope' => 'custom_checkbox',
            'label' => 'Is this a business order? Business T&C\'s apply.',
            'provider' => 'checkoutProvider',
            'visible' => true,
            'validation' => [],
            'sortOrder' => 50,
            'id' => 'custom-field'
        ];


        return $jsLayout;
    }
}
?>

Now create new customCheckbox.js file in this path 'BusinessCheckout/CustomCheckout/frontend/web/js/form/element/' And put tthis content in that new customCheckbox.js JS file.

 define([
    'Magento_Ui/js/form/element/abstract',
    'jquery',
    'uiRegistry'
], function (abstractComponent,jQuery,uiRegistry) {
    uiRegistry.get("checkout.steps.shipping-step.shippingAddress.shipping-address-fieldset.company", function (element) {
        element.disable();
    });
    return abstractComponent.extend({
        hasChanged: function () {
            if (this.value() == true) {
                jQuery('form input[name="company"]').prop("disabled", false);
            } else if (this.value() == false) {
                jQuery('form input[name="company"]').prop("disabled", true);
            }
            return this._super();
        }
    });
});

That hasChanged methode will call while click for check and un-check.

Please run php bin/magento cache:flush and php bin/magento setup:static-content:deploy command after the changes.

4
  • This works in some way however once the page load the checkbox is unchecked and the field is enabled. Only once clicked and unclicked does it function as expected. It should be so that the page loads with the checkbox unchecked and the field disabled.
    – Alexander
    Commented Jul 10, 2018 at 16:09
  • I have updated my answer.
    – kunj
    Commented Jul 11, 2018 at 8:22
  • Awesome, that updated code works perfectly! Thanks a lot for the help.
    – Alexander
    Commented Jul 12, 2018 at 10:11
  • 1
    Welcome, happy to help you and I learn new thing about uiRegistry. we can run custom script after load all UI JS and Content.
    – kunj
    Commented Jul 12, 2018 at 10:16
5

Try this code

Main issue is wrong jquery event.

Your code

jQuery('form input[name="custom_checkbox"]').click(function() {

Replace with

jQuery(document).on('change', 'form input[name="custom_checkbox"]', function(e) {

Full code

<script>
require(['jquery'], function($){
    $(document).ready(function(){

        $('form input[name="custom_checkbox"]').attr('checked', false)
        $('form input[name="company"]').prop("disabled", true);
        $(document).on('change', 'form input[name="custom_checkbox"]', function(e) {
            if ($(this).prop("checked") == true) {

              $('form input[name="company"]').prop("disabled", false);

            } else if ($(this).prop("checked") == false) {

              $('form input[name="company"]').prop("disabled", true);

            }
        });
    });
});
</script>
1
  • @Alexander try this code its work Commented Jul 11, 2018 at 7:41
1

Try to use script like this way:

<script>
require(['jquery', 'jquery/ui'], function(jQuery){ 
 jQuery(document).ready(function(){

  jQuery('form input[name="custom_checkbox"]').attr('checked', false)
  jQuery('form input[name="company"]').prop("disabled", true);

  jQuery('form input[name="custom_checkbox"]').click(function() {

    if (jQuery(this).prop("checked") == true) {

      jQuery('form input[name="company"]').prop("disabled", false);

    } else if (jQuery(this).prop("checked") == false) {

      jQuery('form input[name="company"]').prop("disabled", true);

    }

  });
});

});
</script>
2
  • Still no luck with this unfortunately. Same as before, it works when inputted directly into console but when in the footer nothing happens.
    – Alexander
    Commented Jun 29, 2018 at 8:22
  • If it helps at all here is a link to the site that might give a better idea of what's going on: bit.ly/1resXVE
    – Alexander
    Commented Jun 29, 2018 at 8:40
1

Try the below code:

require(['jquery', 'jquery/ui'], function($){ 
    setTimeout(function(){
        $('form input[name="custom_checkbox"]').attr('checked', false)
        $('form input[name="company"]').prop("disabled", true);

        $('.checkout-index-index form').on('click', 'input[name="custom_checkbox"]', function() {
            if ($(this).prop("checked") == true) {
                $('form input[name="company"]').prop("disabled", false);
            } else if ($(this).prop("checked") == false) {
                $('form input[name="company"]').prop("disabled", true);
            }
        });
    }, 3000);
});

You need use setTimeout for this as Magento 2 load checkout through knockout. On page load elements are not present in the DOM due to this your jquery is not working. You can adjust the time 3000 to your value by checking the time which is perfect for rendering.

2
  • No luck with this unfortunately, even after increasing setTimeout. It seems to work fine in console but when in the footer/header nothing.
    – Alexander
    Commented Jul 10, 2018 at 16:16
  • Can you add custom js file through XML and add the above code to that custom js file and test again Commented Jul 10, 2018 at 16:35
1

You need to keep below code in your JS,

<script>
require(["jquery","domReady!"],function(jQuery) {
    jQuery('form input[name="custom_checkbox"]').attr('checked', false)
    jQuery('form input[name="company"]').prop("disabled", true);

    $('body').on("click",'form input[name="custom_checkbox"]',function() {
        if (jQuery(this).prop("checked") == true) {
          jQuery('form input[name="company"]').prop("disabled", false);
        } else if (jQuery(this).prop("checked") == false) {
          jQuery('form input[name="company"]').prop("disabled", true);
        }
    });
});
</script>
1

You need to rewrite form.html knockout template of Magento_Checkout in your theme.

app\design\frontend\Vendorname\Themename\Magento_Checkout\web\template\billing-address\form.html

replace below div

<div class="billing-address-form" data-bind="fadeVisible: isAddressFormVisible">

to

<div class="billing-address-form" data-bind="fadeVisible: isAddressFormVisible, afterRender: renderedHandler">

Rewrite billing-address.js in your theme

app\design\frontend\Vendorname\Themename\Magento_Checkout\web\js\view\billing-address.js

add below function in above js file

       /**
         * after form render handler
         *
         */
        renderedHandler: function (elements, data) {
         require(['jquery', 'jquery/ui'], function(jQuery){ 
          jQuery(document).ready(function() {

          jQuery('form input[name="custom_checkbox"]').attr('checked', false)
          jQuery('form input[name="company"]').prop("disabled", true);

          jQuery('form input[name="custom_checkbox"]').click(function() {

          if (jQuery(this).prop("checked") == true) {

              jQuery('form input[name="company"]').prop("disabled", false);

          } else if (jQuery(this).prop("checked") == false) {

              jQuery('form input[name="company"]').prop("disabled", true);

          }

          });

         });
         });
        }
1
<script type="text/javascript">
require(['jquery'], function($){
    $(document).ready(function() {
        var flag = 0;
        var existCondition = setInterval(function() {
            if ($('form input[name="custom_checkbox"]').length) {
                if ($('form input[name="custom_checkbox"]').prop("checked") == true) {
                    $('form input[name="custom_checkbox"]').attr('checked', false);
                    flag++;
                }
            }
            if ($('form input[name="company"]').length) {
                if ($('form input[name="company"]').prop("disabled") == false) {
                    $('form input[name="company"]').prop("disabled", true);
                    flag++;
                }
            }

            if(flag == 2) {
                clearInterval(existCondition);
            }
        }, 100);

        $(document).delegate('form input[name="custom_checkbox"]', 'click change', function () {
            if (jQuery(this).prop("checked") == true) {

                jQuery('form input[name="company"]').prop("disabled", false);

            } else if (jQuery(this).prop("checked") == false) {

                jQuery('form input[name="company"]').prop("disabled", true);

            }
        });
    });
});

0

add this in footer js it will work

$(document).ajaxComplete(function()  {
  //add your code here        
});

Your Answer

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

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