0

After I created a module following this tutorial Magento 2.4 Add Recaptcha in Custom From I put my module in a popup and I would like to avoid to load all unnecessary js until I open my popup. I know that this issue comes because I modify the frontend layout

<?xml version="1.0"?>

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">

  <body>
    <referenceContainer name="content">
          <block class="Magento\Framework\View\Element\Template"
                 name="demo.for.recaptcha"
                 template="VendoreName_DemoRecaptcha::form.phtml"
                 >
                <container name="form.additional.info.demo.for.recaptcha">
                  <block class="Magento\ReCaptchaUi\Block\ReCaptcha"
                         name="recaptcha"
                         after="-"
                         template="Magento_ReCaptchaFrontendUi::recaptcha.phtml"
                         ifconfig="recaptcha_frontend/type_for/customform">
                      <arguments>
                          <argument name="recaptcha_for" xsi:type="string">customform</argument>
                          <argument name="jsLayout" xsi:type="array">
                              <item name="components" xsi:type="array">
                                  <item name="recaptcha" xsi:type="array">
                                      <item name="component" xsi:type="string">Magento_ReCaptchaFrontendUi/js/reCaptcha</item>
                                  </item>
                              </item>
                          </argument>
                      </arguments>
                  </block>
                </container>
          </block>
    </referenceContainer>
  </body>
</page>

Is the any method to trigger item when I open my popup?

                                      <item name="component" xsi:type="string">Magento_ReCaptchaFrontendUi/js/reCaptcha</item>

thanks

1 Answer 1

0

You can create mixin for native ReCaptcha and control load

1. Define mixins

app/code/Acme/ReCaptcha/view/frontend/requirejs-config.js

let config = {
    config: {
        mixins: {
            "Magento_ReCaptchaFrontendUi/js/reCaptcha": {
                "Acme_ReCaptcha/js/reCaptcha-mixin": true
            },
            // Example how to handle newsletter signup
            "Magento_Customer/js/block-submit-on-send": {
                "Acme_ReCaptcha/js/block-submit-on-send-mixin": true
            }
        }
    }
};

2. Create ReCaptcha mixin

app/code/Acme/ReCaptcha/view/frontend/web/js/reCaptcha-mixin.js

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

    const mixin = {
        _isObserverRegistered: false,
        _nonTrigger: false,
        useTrigger: function () {
            return typeof this.trigger === 'string';
        },
        initialize: function () {
            this._super();
            this._registerObserver();
        },
        _registerObserver: function () {
            if (this._isObserverRegistered) {
                return;
            }
            this._isObserverRegistered = true;

            if (this.useTrigger()) {
                $('body').on(this.trigger, $.proxy(this._initPopup, this));
            }
        },
        _initPopup: function () {
            if (this._nonTrigger) {
                return;
            }
            this._nonTrigger = true;
            this._loadApi();
            this.renderReCaptcha();
        },
        _loadApi: function () {
            if (this._nonTrigger === true || !this.useTrigger()) {
                this._super();
            }
        },
        renderReCaptcha: function () {
            if (this._nonTrigger === true || !this.useTrigger()) {
                if (typeof this.settings == "undefined") {
                    this.captchaInitialized = true;
                    this.settings = {
                        invisible: true
                    };
                }
                this._super();
            }
        },
        initCaptcha: function () {
            if (this._nonTrigger === true || !this.useTrigger()) {
                this._super();
            }
        }
    };

    return function (target) {
        return target.extend(mixin);
    };
});

3. Example of Extend ReCaptcha settings (Newsletter)

app/code/Acme/ReCaptcha/view/frontend/layout/default.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="recaptcha-newsletter">
            <arguments>
                <argument name="jsLayout" xsi:type="array">
                    <item name="components" xsi:type="array">
                        <item name="recaptcha" xsi:type="array">
                            <item name="trigger" xsi:type="string">show-recaptcha-newsletter</item>
                        </item>
                    </item>
                </argument>
            </arguments>
        </referenceBlock>
    </body>
</page>

4. Mixin to control newsletter form

app/code/Acme/ReCaptcha/view/frontend/web/js/block-submit-on-send-mixin.js

define([
    'jquery',
    'mage/utils/wrapper'
], function ($, wrapper) {
    'use strict';

    return function (newsletter) {
        return wrapper.wrap(newsletter, function (_super, config) {
            _super(config);

            var dataForm = $('#' + config.formId);
            var email = dataForm.find('[name="email"]');

            var fireEvent = function () {
                $('body').trigger('show-recaptcha-newsletter');
            }

            email.blur(fireEvent);
            email.focus(fireEvent);
            email.change(fireEvent);
        });
    };
});

How to use code

  1. Extend your ReCaptcha component with trigger option (see point 3)
  2. Call defined in trigger event name where you want to init recaptcha like $('body').trigger('show-recaptcha-newsletter');
3
  • Ok the trigger works in a way to show or not the item, but I was looking how to load the ReCaptcha Js only. Maybe I am doing something wrong Aug 23, 2022 at 11:00
  • ReCaptcha should be load once form render. The mixin prevent to load ReCaptcha and load only when trigger called. To be sure you don't have any other recaptcha elements on page. This solution from one of my project and it works properly with popup. Or provide more details what are you doing and what are you expect Aug 23, 2022 at 15:56
  • When you says that "ReCaptcha should be load once form render" that means that all the Js such like reCaptcha.js, reCaptcha-mixing.js, reCaptchaLogin-mixin.js, registry.js, reCapchaScriptLoader and noninlineReCaptchaRenderer.js that belong to the component they have to be loaded at least once before to call the trigger. Can They not be loaded just before I use the trigger? I would like to avoid loading many js around page. I don't know if it is possible :(. btw your trigger is working thanks Aug 24, 2022 at 15:51

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.