4

I have a project set up with Drupal loading in RequireJS which has a jQuery dependency defined.

All is well and good until I try something like this in a RequireJS managed module:

    (function($, Drupal) {
        Drupal.behaviors.someModuleName = {

            attach: function(context, settings) {
               // Some functional stuff here
            }
       };
    }(jQuery, Drupal));

The problem is that the attach function does not get called which leads me to think that Drupal is firing off its behaviours loader before Require has loaded up its modules.

1

Woops, I'm not sure how the explanation got lost!

The script include:

<script id="requirejs" data-rev="1485975293" data-main="main.js?rev=1485975293" src="require.js?rev=1485975293"></script>

Alright, so this is in my main.js (data-main) file, that requirejs uses for loading up the dependencies and all that.

I'm just posting the relevant code block here (notice the Drupal.attachBehaviors(document, Drupal.settings); at the end:

    require([
      'jquery',
      'underscore',
      'intentcontext',
      'app',
      'primary-menu'
      ], function ($, _, IntentContext, app) {
      'use strict';

       // DOM ready
      $(function() {

        // js loaded only on homepage
        if ($('body').hasClass('front')) {
          require(['homepage']);
        }

        /*
         * loaded js for foundation and intention
         */
        require(['foundation']);
        require(['intentinit']);

        // call drupal behaviors
        Drupal.attachBehaviors(document, Drupal.settings);
      }); // DOM ready
    });

And then example of a dependent js module (primary-menu.js):

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

      /*
       * constructor
       */
      var PrimaryMenu = function(context, settings) {
        var
          self = this;

        self.$elm = $(context).find('#block-system-main-menu');
        $('body').once('primaryMenu').each(function() {
          self.init();
        });
      }; // PrimaryMenu constructor

      /*
       * on document ready with drupal behaviors
       */
      (function($, Drupal) {
        Drupal.behaviors.primaryMenu = {
          attach: function(context, settings) {
            var
              primaryMenu = new PrimaryMenu(context, settings);
          }
        };
      }(jQuery, Drupal));
    });

Hope that helps.

  • Explanation added :) – Micah J Feb 1 '17 at 20:09
  • Much better, merci! – Pierre.Vriens Feb 1 '17 at 20:11
0

If RequireJS is loading your application's modules asynchronously once the page is loaded, then there is a high chance that Drupal's own page load handler will attach behaviors before your modules had their chance at registering theirs.

Because the are attached using the jQuery ready event, you may be able to jQuery.holdReady() to delay jQuery's ready event processing to after your application is loaded.

Another solution would be to call Drupal.attachBehaviors(document, Drupal.settings); time once your application is fully loaded. Properly written behavior should no have issue being attached multiple times to the page.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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