0

I have a form elements that looks like this:

  $form['properties'][$property->idProperty] = array(
    '#title' => $property->Label,
    '#ajax' => array(
      'callback' => 'mymodule_filter_ajax',
      'wrapper' => 'mymodule-filter-result',
      'method' => 'replace',
      'effect' => 'fade',
    ),
    '#attributes' => array(
      'autocomplete' => 'off',
      'class' => array('exclusive'),
      'exclusivity_group' => array ( $property->ExclusivityGroup )
    ),
  );

The point of it is to have only one element from each group used at a time. To enforce that exclusivity, I created behavior like this:

(function($) { 
  Drupal.behaviors.behavior_name = {
    attach: function (context, settings) {

      $('select.exclusive', context).on('change', function(){
        // Make all not selected
        $("[exclusivity_group='"+$(this).attr('exclusivity_group')+"']").not(this).find("option").attr('selected', false);
        // select "all"
        $("[exclusivity_group='"+$(this).attr('exclusivity_group')+"']").not(this).find("option[value='all']").attr('selected', true);
      });
    }
  };
})(jQuery);

Note that both code blocks above are simplified, please don't criticize it too much as this is not actual code I'm using posted verbatim.

How can I make sure my behavior acts before AJAX? If it happens to act after AJAX, I may end up with two fields set to something other than 'all', and that's specifically what I wanted to avoid. I may use $triggering_element to detect if it was one of "exclusive" fields, and I probably will, even if only as a secondary precaution, but I would strongly prefer to have things happening right in the JavaScript part.


I tried using this answer, but I don't think I understand how it works. I tried:

  $('select.exclusive', context).each(function(){
    console.log($(this).attr('id'));
    Drupal.ajax[$(this).attr('id')].options.beforeSubmit = function (form_values, element, options) {
      console.log(element.html());
    };
  });

First console.log returns IDs as expected. And it works, beforeSend is, indeed, changed as it should, it's function gets executed when needed. Sadly console.log(element.html()); returns content of a whole form, not the triggering element of AJAX, so I'm not able to safely enforce exclusiveness - I don't know which element was changed last, so no way to select other elements.

1

I got it working now. The way to do it was:

  • Get all elements that are in "exclusive" groups using classes, .each over them
  • For each element, change beforeSubmit using $(this).attr('id') as index for ajax table
  • Because I was not able to get element to point to a specific element (it always pointed to entire form), I used helper variable at the beginning of .each loop.

Resulting code is like this:

(function($) { 
  Drupal.behaviors.behavior_name = {
    attach: function (context, settings) {

      $('select.exclusive', context).each(function(){
        var triggering_element = $(this);
        Drupal.ajax[$(this).attr('id')].options.beforeSubmit = function (form_values, element, options) {
          // Make all not selected
          $("[exclusivity_group='"+triggering_element.attr('exclusivity_group')+"']").not(triggering_element).find("option").attr('selected', false);
          // select "all"
          $("[exclusivity_group='"+triggering_element.attr('exclusivity_group')+"']").not(triggering_element).find("option[value='all']").attr('selected', true);

        };
      });
    }
  };
})(jQuery);

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.