I need to create a pair of dynamically interacting selects. The content in the actual exposed filter needs to be grouped, so i added a select with the group names that should, on change, load the coresponding items in the second select (the exposed filter).

I used hook_form_alter to add the select that triggers the ajax call.
My problem is that the ajax call does not trigger the callback function. I tested the same code in the form_alter of a node's add page, and they work correctly.
Any suggestions?

CommentFileSizeAuthor
#154 views-ajax_callback-1183418-154-D7.patch4.38 KBLiam Morland
#152 views-n1183418-152.patch4.29 KBpbirk
#146 views-n1183418-146.patch4.3 KBDamienMcKenna
#146 views-n1183418-146.interdiff.txt893 bytesDamienMcKenna
#145 views-n1183418-145.patch4.28 KBDamienMcKenna
#145 views-n1183418-145.interdiff.txt4.04 KBDamienMcKenna
#140 views-exposed_form_ajax_support.patch4.16 KBomnia.ibrahim
#129 views-n1183418-128.interdiff.txt3.73 KBDamienMcKenna
#129 views-n1183418-128.patch4.2 KBDamienMcKenna
#126 1183418-126.views-exposed-filter-with-ajax.d8.patch4.94 KBdww
#119 views_vexp_ajax.zip2.96 KBjncruces
#116 views-exposed_form_ajax_support-1183418-106.patch4.17 KBjoelpittet
#106 views-exposed_form_ajax_support-1183418-106.patch4.17 KBbarraponto
#73 views-exposed_forms_ajax_support-1183418-73.patch4.15 KBjonhattan
#72 views-exposed_forms_ajax_support-1183418-72.patch3.31 KBbneel
#63 error.png28.85 KBDartDruart
#47 Screen Shot 2013-04-13 at 13.00.44.png98.82 KBlathan
#47 Screen Shot 2013-04-13 at 13.01.02.png40.4 KBlathan
#47 addressfield_views_handler_filter_administrative_area.inc_.zip1.53 KBlathan
#46 views-exposed_forms_ajax_support-1183418-46.patch4.23 KBInternetDevels
#45 views-exposed_forms_ajax_support-1183418-45.patch4.29 KBInternetDevels
#41 views-exposed_forms_ajax_support-1183418-41.patch2.98 KBInternetDevels
#37 views-exposed_forms_ajax_support-1183418-37.patch2.46 KByannickoo
#33 views-exposed_forms_ajax_support-1183418-33.patch2.46 KByannickoo
#31 views-exposed-forms-ajax-support-1183418-32.patch2.46 KBbarraponto
#30 views-exposed-forms-ajax-support-1183418-30.patch2.34 KBbarraponto
#28 views-exposed-forms-ajax-support-1183418-28.patch2.32 KBbarraponto
#26 views-exposed-forms-ajax-support-1183418-26.patch2.32 KBbarraponto
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

andreicio’s picture

Update:

First problem: views preprocesses only the filters defined and exposed, ignoring all other widgets. The result is that the "form_id", "form_build_id" and "form_token" did not make it into the form, so the ajax call was incomplete. I added them to the #info array, so they would be rendered as filters.

Second problem. They arrive in the preprocess function with the #access set to false. I hacked it to set it to true, and it worked. Now the ajax works.

Current problem: Filtering no longer works. The list loads correctly, but when I click the filter button, even without setting any filter, there are no results. If I just comment the #ajax part for the widget I added then it all works, so it's not an issue with the newly added filters but rather with the js. I'm stuck again :(

merlinofchaos’s picture

Views are $_GET forms and they specifically remove the form_id and form_build_id and form_token because they are 'submitted' even when they aren't submitted. That means the standard #ajax tools don't work with them, since those rely on being able to cache the form in core's form cache. That system is to naive to work with core's filters. I've never really tried to do anything like this in D7 yet, so I don't know what the solutions might be, but I can say that it's going to provide very ugly URLs if you hack the form id back in.

joelstein’s picture

andreicio: Can you please post what you used to do this? I'm trying to do the exact same thing, and it just won't work for Views forms.

andreicio’s picture

Ok, I made it work.
@merlinofchaos, I would love to read your comments on this idea. Maybe it can be implemented in a cleaner way inside views.

So. The only problem was that the ajax call needs form information in order to work (access form from cache) while views needs that information omitted (access form NOT from cache). My solution was to add an invisible and disabled select with all info in it, then add the info when ajax is called.

In php, inside the hook_form_alter() for the views exposed form:

$form['form_information'] = array(
		'#prefix' => '<div style="display:none">',
		'#suffix' => '</div>',
		'#type' => 'select',
		'#disabled' => true,
		'#options' => array(
				'form_id' => $form['#form_id'],
				'form_build_id' => $form['#build_id'],
				'form_token' => $form['#token'],
				),
		);

In js, override the Drupal.ajax.prototype.beforeSubmit function with this one:

function (form_values, element, options) {
	$('select:disabled option').each(function(){
             form_values.push({'name':$(this).val(),'value':$(this).text()});
             });
}

This way, if an ajax call gets made, the form info gets submited, while views' exposed filters stay clean.

One last note: in the ajax tutorial they tell you to expect the submited values in $form_state['values']. That is true for the ajax call, but if you just submit the exposed filters form, the values are in $form_state['input']. So you should do something like this:

$default = !empty($form_state['input']['yourajaxedelement']) ? $form_state['input']['yourajaxedelement'] : 'empty_value';
$default = !empty($form_state['values']['yourajaxedelement']) ? $form_state['values']['yourajaxedelement'] : $default;
joelstein’s picture

Perfect! Thank you very much for this. I was able to get my form_alter and Ajax callback working, thanks to your explanation.

(It was even more cumbersome for me, since I needed to alter two filters based on the value of one filter, and since Views wraps the filter widgets in it's own classes, the #prefix and #suffix settings don't allow you to wrap two fields together nicely. I had to return my whole form in my Ajax callback, and manually reset the $form['#method'] to "get" to make it work.)

Still, I wish there was a way to do this in a more elegant way. Perhaps we could assign some form value which Views could look for, and if it was present, the Javascript you have above would populate the form values on Ajax submit. We don't necessarily need to pass a select value, though. We could just as easily pass those values as Drupal Javascript settings (which makes sense, since it deals with Ajax).

merlinofchaos’s picture

Version: 7.x-3.0-beta3 » 7.x-3.x-dev
Component: exposed filters » Documentation
Category: support » task

That's a really awesome way to do it. Sadly a little bit manual, but it will do the trick. This should be documented somewhere, because people will need to know how to do this.

This would be good for the API section of the advanced help.

andreicio’s picture

Ok. Updated version: This code is the ajax fix that needs to go in hook_form_views_exposed_form_alter():

/* AJAX fix */
$js_code="jQuery(function(){
			for(ajax_object in Drupal.ajax) 
				if(Drupal.ajax[ajax_object].options)
					jQuery.extend(Drupal.ajax[ajax_object].options.data,Drupal.settings.exposed_form_info);
				});";
$form_info_array = array(
	'form_id' => $form['#form_id'],
	'form_build_id' => $form['#build_id'],
	'form_token' => $form['#token'],
	);
drupal_add_js(array('exposed_form_info' => $form_info_array), 'setting');
drupal_add_js($js_code,array('type' => 'inline', 'weight' => 100));

Only one problem remains after this. As I mentioned before, submited values can be found in $form_state['input'] for a normal views submit and in $form_state['values'] for an ajax call. One solution is:

if(!empty($form_state['values'])) {
	$form_state['input'] = array_merge($form_state['input'],$form_state['values']);
}

After that the default values for widgets will always be found in $form_state['input'] even for ajax calls.


And another note:
If you want to position your extra widget(s) in the exposed filters form you need to also add info to the $form['#info'] array in the correct position.
For example, to add a "brand_selector" widget right before a filter called "model_selector":

foreach($form['#info'] as $id => $stuff) {
	if($id=='model_selector') {
		$tempinfo['brand_selector'] = array('label'=>'Brand', 'value'=>'brand_selector);
	}
	$tempinfo[$id] = $stuff;
}
$form['#info'] = $tempinfo;



@joelstein:
I had to do similar stuff. One option is to copy views-exposed-form.tpl.php to views-exposed-form--YOUR_VIEW_NAME.tpl.php that will be applied for your particular view, and edit that.

joelstein’s picture

Using Javascript settings is a nice solution, but my form now only behaves correctly on the first Ajax request. Since I am returning the entire form via Ajax, I'm guessing that the behavior needs to be re-attached or something after the first Ajax response. (I tried using the template file, but couldn't get it to work... not even after I flushed my caches... strange.)

Here's a solution which is working for me, using a Drupal "behavior". This can be done in a form_alter function... or, we can have Views sniff the form for any #ajax elements, and then add the Javascript if it finds some. Here's a proposed new version of views_form_views_exposed_form_alter().

/**
 * Implement hook_form_alter for the exposed form.
 */
function views_form_views_exposed_form_alter(&$form, &$form_state) {
  // Since the exposed form is a GET form, we don't want it to send a wide
  // variety of information.
  $form['form_build_id']['#access'] = FALSE;
  $form['form_token']['#access'] = FALSE;
  $form['form_id']['#access'] = FALSE;

  // In order for Ajax to work, we need the form build info. Here we check if 
  // #ajax has been added to any form elements, and if so, pass this info as
  // settings via Javascript, which get attached to the submitted form on Ajax
  // form submissions.
  foreach (element_children($form) as $key) {
    if (isset($form[$key]['#ajax'])) {
      $form['#attached']['js'][] = array(
        'type' => 'setting',
        'data' => array(
          'exposed_form_info' => array(
            'form_id' => $form['#form_id'],
            'form_build_id' => $form['#build_id'],
            'form_token' => $form['#token'],
          ),
        ),
      );
      $form['#attached']['js'][] = array(
        'type' => 'inline',
        'weight' => 100,
        'data' => '(function ($) {
            Drupal.behaviors.ViewsExposedFormAjax = {
              attach: function(context, settings) {
                for (ajax_object in Drupal.ajax) {
                  if (Drupal.ajax[ajax_object].options) {
                    jQuery.extend(Drupal.ajax[ajax_object].options.data, Drupal.settings.exposed_form_info);
                  }
                }
              }
            };
          })(jQuery);',
      );
      break;
    }
  }
}

Still to be considered is where we'd merge the $form_state['values'] and $form_state['input'] arrays.

andreicio’s picture

Nice. I'm rather new to drupal, and still unsure how to use behaviors. Your solution is perfect.
The first 3 lines aren't needed though, since #access already is false, or at least it was for me. I had to change it to true in order to get them to render.
The foreach loop could even be integrated in views, I'd say. merlin's choice, I guess.

joelstein’s picture

Look a little closer... I was actually implementing this within Views in the example above. :)

andreicio’s picture

Ah. Even nicer! :)

merlinofchaos’s picture

Changing this to behaviors basically means changing this:

jQuery(function(){

to this:

Drupal.behaviors.SOMEUNIQUENAMENMERE = function () {

And making sure the ) is rebalanced at the end.

joelstein’s picture

Yep, that's what I did in #8 above.

andreicio’s picture

Question: views_form_views_exposed_form_alter is an implementation of hook_form_views_exposed_form_alter, right? If so, how do you know it's the last one to run? If i have mymodule_form_views_exposed_form_alter that creates a #ajax, then it has to come first, in order to actually have a #ajax that the foreach loop can find.
If indeed this is a issue, wouldn't this code work better in the template_preprocess_views_exposed_form function?

merlinofchaos’s picture

Views is module weight 10 -- the vast majority of modules are lighter than this. We can't guarantee it's last but it'll be nearly last.

neoglez’s picture

Just for the record, very nice (and clean) things can be achived by taking advantage of the now (Views 3) available exposed form plugin implementation.

nicodv’s picture

Hi there, I see the level of this conversation is higher than my knowledge, but i need to constructo a user (register and profile) form_alter including an ajax dependent dropdown and I have THE problem: ajax don´t work.
So, after reading this thread I more or less understood everything but I see you didn´t say anything final about the merging of $form_state['values'] and $form_state['input'] arrays... where do I have to place it?

Any help will be really welcome (It took me 3 days to finish the dropdowns :P)

Thanks a lot.

nico

merlinofchaos’s picture

#17: Sorry but this discussion is about views exposed filters, which are a very special form. This is not an appropriate place to ask about other forms.

mdrechsler’s picture

Using the code in #8 allows my hook_alter AJAX code to "work" for an exposed view filter, and I'm trying to set my $form_state['values'] and $form_state['input'] to be the same, but submitting the form doesn't return any results, and I'm not sure how to check to be certain all my fields are being passed properly. I was thinking of setting them equal as part of the callback function, but those are only called for 2 of my 3 fields.
If I do a dpm($form) or dpm($form_state) as part of my callback I think I can see the inputs getting set, but I'm not sure where to set them for certain for the submit. I tried hooking into hook_submit to set them but didn't have any luck with that.
I hope I'm not rambling too much, I've very new to Drupal development, and feeling very frustrated.
I'm not even sure its the inputs holding me back at this point. Could anyone share some working code?

paolomainardi’s picture

Thanks guys, you made my day! It works like a charm.

32i’s picture

Follow-up to #8 and why solution mentioned in #7 working only first time - it's simple, after first request, select lose it's wrapper, so on second call, ajax don't have the wrapper where it should put the response.

So, it can be fixed by wrapping the element returned by callback in the same wrapper.

gillarf’s picture

Thanks from me too - exactly what I needed.

Can this go into View hacks?

ACD’s picture

Guys, so what is the last working variant for this?
I used the code mentioned in #7, but it work only for one element. But I have 3 select fields, each depends on the others, so when I changed the 2nd - the 3rd doesn't change. Any ideas why?
Thanks in advance

P.S.: I took the code from #8 and put it in the end of my hook_form_alter and it works properly. (at the first time it didn't). Thanks a lot!

gilzero’s picture

Sub +1

barraponto’s picture

Category: task » feature
Status: Active » Needs work

So, basically, can we:

  1. Put the behavior in a separate file?
  2. Add a process after_build to the exposed form elements, so that IF they have ajax properties, they get this hacks by default?

I'll try and put up a patch once I get this hack working.

barraponto’s picture

Component: Documentation » exposed filters
Status: Needs work » Needs review
FileSize
2.32 KB

So, I moved all of the javascript logic to a separate file, and all of the PHP logic into an #after_build callback. What's left is the merger of $form_state['values'] and $form_state['input']. After_build is too late to merge, but views' form_alter is too late as well. We're doomed to merge (if we want to) in our own form alter hooks.

Of course, this needs documentation (but way less documentation than before).

Status: Needs review » Needs work

The last submitted patch, views-exposed-forms-ajax-support-1183418-26.patch, failed testing.

barraponto’s picture

Status: Needs work » Needs review
FileSize
2.32 KB

I had already seen that coming.

Status: Needs review » Needs work

The last submitted patch, views-exposed-forms-ajax-support-1183418-28.patch, failed testing.

barraponto’s picture

Status: Needs work » Needs review
FileSize
2.34 KB

keep posting the wrong patch...

barraponto’s picture

Actually, anonymous users don't (usually) get tokens. right?

RogerRogers’s picture

Just wanted to say that I applied the patch from #31 and it worked. Thank you barraponto!!!

yannickoo’s picture

I just renamed the file to exposed-form-ajax.js (replaced the underscores to dashes) and I replaced ajax_object with ajaxObject. In Javascript you should use camelCase. I think we have to check the callback because this was an issue in another module.

scottrigby’s picture

After applying #33 I was finally able to use FAPI #ajax params on exposed filters.

barraponto’s picture

@yannickoo can you elaborate on the callback issue? I want to see this commmited.

yannickoo’s picture

Status: Needs review » Needs work

I will work on that later okay?

yannickoo’s picture

Status: Needs work » Needs review
FileSize
2.46 KB

The callback issue is not easy to solve because you can set the name of the callback. On "Manage display" there is a callback "field_ui_display_overview_multistep_js" which we don't want to extend with the exposed form info.

The patch uses "ViewsExposedFormInfo" instead of "exposed_form_info" as Drupal.settings name.

It is strange that I have no drag&drop issues like earlier.

Bart Vanhoutte’s picture

#37 does the job.

InternetDevels’s picture

Status: Needs review » Needs work

# 37 breaks any other forms with #ajax on the same page. ajax_get_form() receives wrong form_biuld_id after the patch applied.

yannickoo’s picture

Okay that is the problem I expected... We have to check the callback name but I don't know how we can get it hm :/

And does the patch work for multiple altered exposed forms?

InternetDevels’s picture

Status: Needs work » Needs review
FileSize
2.98 KB

Attached patch fixes both other forms with #ajax and multiple altered exposed forms, but I'm not sure about the way it is done.

Nicolas Bouteille’s picture

Hi,

Patch #41 works for me except when I use ajax along with the module Views Dependent Filter that hides exposed filters via Ajax too. Looks like there is a conflict somehow, I opened a separate issue not to mess with the readability of this one but if you guys could help me out on that one too that would be awesome.

http://drupal.org/node/1959370

Thanks!

lathan’s picture

Status: Needs review » Needs work

This patch is not working for me i keep getting 'Invalid form POST data.' http://drupal.org/node/1922342 when trying to add a dependant drop down to an views filter option form.

Something like this.

{
  $form['computer_stats']['os'] = array(
    '#title' => t('Operating system'),
    '#type' => 'select',
    '#options' => drupal_map_assoc(array('', t('OSX'), t('Linux'), t('Windows'))),
    '#ajax' => array(
      'callback' => 'input_os_verify_ajax_callback',
      'wrapper' => 'input_os_verify_wrapper',
     ),
  );

  // Setting an empty element with a wrapper to be populated.
  $form['computer_stats']['os_verify'] = array(
    '#type' => 'markup',
    '#prefix' => '<div id="input_os_verify_wrapper">',
    '#suffix' => '</div>',
  );

  // When submitted, check for value of OS, and populate os_verify.
  if (isset($form_state['values']['os'])) {
    $form['computer_stats']['os_verify']['#type'] = 'checkbox';
    $form['computer_stats']['os_verify']['#title'] = t('Are you sure you are using @os?', array('@os' => $form_state['values']['os']));
  }

  ...
}


function input_os_verify_ajax_callback($form, $form_state) {
  return $form['computer_stats']['os_verify'];
}
bsuttis’s picture

Wanted to chime in and say the patch at #41 works against 7.x-3.7, thanks.

InternetDevels’s picture

Status: Needs work » Needs review
FileSize
4.29 KB

Problem was in element_children(), which looked only on the first level of the form. Attached patch should fix this behavior.

InternetDevels’s picture

Forgot to remove console.log from js.

lathan’s picture

That is still failing for me. I have attached screen shots and the views_handler_filter_in_operator i have extended that I am using.

frankdesign’s picture

Just to let you know, patch at #46 worked for me on Views 7.x-3.7.

barraponto’s picture

@jucallme what version of views were you using?

lathan’s picture

Im on the 7.x-3.x branch specifically commit f7cb51aad6943973e22197d54d202453292d6a27

doliveros’s picture

I can also confirm that #47 worked. It should be committed IMO.

EDIT: Sorry guys, I meant #46, not #47

barraponto’s picture

We have some feedback calling for RTBC, but @jucallme says it doesn't work with that particular commit. @jucallme can you try upgrading your views module? that commit is pre 3.6.

yannickoo’s picture

Guys, why do you say that #47 should be committed? There is only a zip file with a file which extends views_handler_filter_in_operator class. That isn't a patch and I don't know how it is related to this issue here.

lathan’s picture

@barraponto i have updated views to the latest dev code and i am still getting this error.

To make it easier for other to test this issue i have created a sandbox with this handler.
git clone --branch views_form_alter_test jucallme@git.drupal.org:sandbox/jucallme/1978134.git addressfield

enable addressfield and create a view with an administrative area field filter. Selecting the country throws the error i have been speaking about. The code associated with that can be found in addressfield_views_handler_filter_administrative_area.inc

yannickoo’s picture

#54 are you sure that you are in the right issue? This looks more like an Address Field issue what you try to do.

barraponto’s picture

@yannickoo I guess we're saying #46 is rtbc-candidate, but #47 points to a possible issue.

lathan’s picture

@yannickoo Read #43 there i point out what i am doing in the patch to addressfield.... in which i need to implement a dependant drop down to an views filter option form. I have attached what i am working on simply for your connivence to test this case where by this patch here is failing. Else follow the steps i pointed out in #43 and implement your own dependant drop down in a views options form and you will have the same experience.

InternetDevels’s picture

@jucallme, sorry for taking so long to reply. I've looked more closely at your code attached at #47. Your problem isn't related to the exposed forms, but to the views handler's settings form. Please consider views_handler::options_form() and it's usage in the views_ui/includes/admin.inc. Views uses some own mechanism for ajax processing.

Anyway, I'm not sure that solution used for the exposed forms can help for handler options form. I may try to find any other way, but I think it should be a separate issue.

barraponto’s picture

Status: Needs review » Reviewed & tested by the community

@InternetDevels can we mark this as RTBC again?

fortis’s picture

i think we can just use hook_views_ajax_data_alter(&$commands, $view) and $view->exposed_raw_input
and it's better way
ps:// SFME

Mixologic’s picture

Status: Reviewed & tested by the community » Needs work

Im having some troubles with the patch in #46. For some reason the normal exposed filter, when used in a block, becomes a POST instead of a GET. If I comment out line 17 of the javascript file, jQuery.extend(Drupal.ajax[ajaxObject].options.data, Drupal.settings.ViewsExposedFormInfo[name]);, then it stays as a GET.

Hmm. Actually this is because Im replacing the whole form as I've got seven dropdowns that are interdependent upon each other. If I dont explicitly set the form method to GET it comes back to the ajax call as POST.

Mixologic’s picture

Status: Needs work » Reviewed & tested by the community

Setting status back.

DartDruart’s picture

FileSize
28.85 KB

Hi guys, I'm tried to make two interdependent dropdowns. I'm using #7 and has encounter error in ajax.js in line 133 (Has anyone encountered this error). I tried to catch it and discovered, that element_settings.url become as array.

I'm using this code in my module


function braino_hooks_form_alter(&$form, &$form_state, $form_id)
{
    if(!empty($form_state['values'])) {
        $form_state['input'] = array_merge($form_state['input'],$form_state['values']);
    }

    if ($form['#id'] == 'views-exposed-form-muskus-duck-page') {

      $selectedNumb = isset($form_state['input']['field_numb_value_selective']) ? $form_state['input']['field_numb_value_selective'] : 'all';
      $selectedList = isset($form_state['input']['field_list_value_selective']) ? $form_state['input']['field_list_value_selective'] : 'all';

      $form['field_list_value_selective']['#options'] = _get_associative_array_from_view(
        'deleteme', // view id
        'default', // view display id
        'field_data_field_list_field_list_value', // key field id
        'field_data_field_list_field_list_value', // value field id
        $selectedNumb
      );
      
      $form['field_numb_value_selective']['#options'] = _get_associative_array_from_view(
        'eatme', // view id
        'default', // view display id
        'field_data_field_numb_field_numb_value', // key field id
        'field_data_field_numb_field_numb_value',
        $selectedList // value field id
      );

      $form['field_list_value_selective']['#ajax'] = array(
        'callback' => 'ajax_update_numb_callback',
        'wrapper' => 'numb_wrapper',
        'effect' => 'fade',
        'event' => 'change',
        //'method' => 'replace',
        'progress'=> array('type'=> 'throbber', 'message' => t('Please wait...')),
      );

      $form['field_numb_value_selective']['#ajax'] = array(
        'callback' => 'ajax_update_list_callback',
        'wrapper' => 'list_wrapper',
        'effect' => 'fade',
        'event' => 'change',
        //'method' => 'replace',
        'progress'=> array('type'=> 'throbber', 'message' => t('Please wait...')),
      );

      $form['field_numb_value_selective']['#prefix'] = '<div id="numb_wrapper">';
      $form['field_numb_value_selective']['#suffix'] = '</div>';

      $form['field_list_value_selective']['#prefix'] = '<div id="list_wrapper">';
      $form['field_list_value_selective']['#suffix'] = '</div>';


      /* AJAX fix  */
     $js_code="jQuery(function(){
                  for(ajax_object in Drupal.ajax) 
                    //alert(Drupal.ajax[ajax_object].options);
                    if(Drupal.ajax[ajax_object].options)
                    {
                      jQuery.extend(Drupal.ajax[ajax_object].options.data,Drupal.settings.exposed_form_info);
                      //alert(Drupal.settings.exposed_form_info.form_id);
                    }
                  });";
      $form_info_array = array(
          'form_id' => $form['#form_id'],
          'form_build_id' => $form['#build_id'],
          'form_token' => $form['#token'],
          );
      drupal_add_js(array('exposed_form_info' => $form_info_array), 'setting');
      drupal_add_js($js_code,array('type' => 'inline', 'weight' => 100));

      if(!empty($form_state['values'])) {
          $form_state['input'] = array_merge($form_state['input'],$form_state['values']);
      }
    //echo '<pre>'.print_r($form['field_list_value_selective']['#ajax'],1).'</pre>';

    }
//  }
}


function ajax_update_numb_callback($form, $form_state) {
  return $form['field_numb_value_selective'];
}

function ajax_update_list_callback($form, $form_state) {
  return $form['field_list_value_selective'];
}

function _get_associative_array_from_view($viewID, $viewDisplayID, $keyFieldID, $valueFieldID, $contextualFilter){
  
  $associativeArray = array();
  $associativeArray['All'] = t('- Any -');
  $viewResults = views_get_view_result($viewID, $viewDisplayID, strtolower($contextualFilter));
  foreach($viewResults as $viewRow) {
    $associativeArray[$viewRow->$keyFieldID] = $viewRow->$valueFieldID;
  }
  
  return $associativeArray;
}


Has anyone encountered this error?

danharper’s picture

Has this been committed yet?

I could do with this patch but don't fancy using patched version of views on a live site.

Cheers

thesame-’s picture

I'm also interested in this. Is this going to be committed?

mr_scumbag’s picture

I just needed this, and patch at #46 is not committed to views, so I needed to apply it myself.

I applied the patch at #46, and my ajax powered views exposed form now works just like regular FAPI ajax powered forms do. Using hook_form_views_exposed_form_alter() to add the ajax

Is this patch expected to be committed to Views?
(It adds really useful functionality, which makes views hook_form_alter() with ajax work just like it should.)

barraponto’s picture

I guess everyone is on the D8 bandwagon... but you can try mailing the mantainers through the contact form.

heddn’s picture

#46 RTBC on yet another site.

mareks’s picture

I can confirm that #46 works for my form_views_exposed_form_alter with Views 7.x-3.7. It nicely reacts to my select list changes.

However, it does not seem to do anything when I enable Better Exposed Filters module (BEF) and change the "Default select list" to "Checkboxes/Radio buttons".

Maybe I'm holding it wrong :) Can anyone else test the Radio buttons vs Default select list use case?

In case of a radio buttons, should the callback be coded differently?

Thanks,

bneel’s picture

#46 works great, but if you have a dynamic form with new subform appearing after ajax call (like herarchical select form). The drupal.settings contain form_info for the initial form, not the updated form. Hence, the newly subform does note trigger the callback.

To resolve this issu, don't attach setting to the form in the #after_build callback, but use drupal_add_js().

change

$form['#attached']['js'][] = array(
      'type' => 'setting',
      'data' => array(
        'ViewsExposedFormInfo' => $ajax_info,
 ),

To

  drupal_add_js(array(
        'ViewsExposedFormInfo' => $ajax_info), 'setting'
    );

drupal_add_js() update the drupal.settings, not the settings attached to the form.

barraponto’s picture

@bneel can you provide a patch?

bneel’s picture

ET voilà

jonhattan’s picture

geekygnr’s picture

I applied #73 to 7.x-3.7 while trying to do this and it works great.

henk’s picture

#73 confirm, works for me also, thanks!

mas0h’s picture

After applying #73, when trying to add new filter to the view I can't search for fields now in the view when selecting filters or fields, no matter what I write in search field values don't change.

geekygnr’s picture

@mas0h I can't replicate the problem you described. What version of views did you apply #73 to?

mas0h’s picture

Greetings Geekygnr,

I applied the patch against 3.7, but I suspect this issue is related to this module https://drupal.org/node/2168371
It is supposed to limit views exposed filter to the used terms in the results.

frankdesign’s picture

Hi, Has anyone got this working on Views 7.x-3.8? I'm anxious to upgrade as it is a security update but the patches at #46 and #73 only seem to work on Views 7.x-3.7.

Thanks

F

i.bajrai’s picture

#73 does not work in views 7.x-3.8.

line 2077 views.module
remove weight from the attachment and all works again.

dariogcode’s picture

I can confirm it is working with latest 7.x.-dev version.

aleksijohansson’s picture

Also confirming that #73 works with Views 7.x-3.7. Tested on a view that is somewhat complex.

Vj’s picture

Tested the patch #73 with views 7.x-3.8 and it works great :)

pcrats33’s picture

Tested patch #73 on views 3.8 finally got it working. I'm not sure if this patch is just for the Reference Option Limit module or for other things as well, but I want to stress the importance of good documentation. It took me a week to figure out how to use this module, and mostly by reading and re-reading error issues. Without proper documentation a lot of time and energy is wasted, please document well! For this particular patch, it took me a while to realize how views AJAX exposed forms would work. Hitting apply worked, but I didn't realize you have to set EXPOSED FORM, Exposed form style: | Settings: check Autosubmit and Hide Submit button. That may be basic knowledge to some, but not everyone knows this. My problem was also with another bad jQuery add on with the site I was working on that transforms select boxes to div wrapped a href dropdowns, but that's another story, and i'd pull that code if I had the choice. So yes, the patch works, and please please document well. And be well.

dieuwe’s picture

Patch #73 works perfectly with 3.8, no changes required.

pmkanse’s picture

Patch #73 tested with views 7.x-3.8 and it works great \m/\m/.

c.dan’s picture

Patch #73 tested and works on views 7.x-3.10.

TuWebO’s picture

Hi,
Patch #73 is working fine for me too on views 7.x-3.8, just as is, I didn't need to change the weight (as #80 mentioned).

My use case:
I have a view with 3 exposed filters as text fields, and also have the view with the settings "Exposed form in block" to "Yes" and "Use Ajax" set to "No".

I'm able to hook into "MYMODULE_form_views_exposed_form_alter", change those fields to select list and make them dependant one on each other with no problem, before this patch the ajax didn't work. That's the test that I made.

I can also confirm that (in my case) the plugin geofieldProximityExposedFilter from the geofield module, throws an error when aplying this patch, I will try to find the problem and post an issue for this.

Thanks for this great patch to everyone involved on it.

baikho’s picture

Patch #73 also works for Views 7.x-3.10 Thanks!

Drupaltarzen’s picture

I dont know any coding , I need this functionality, what should i do ..

1) Where should this patch be placed.
2) I need the exposed filter to search/filter on 4 fields
3) Any modules other then view's ? needs to be installed here ?,

Please guide.

Thanks

Vj’s picture

@Drupaltarzen
Save patch in your views module folder. Then run
git apply -v views-exposed_forms_ajax_support-1183418-73.patch

If patch applied successfully then you should get it working.

Drupaltarzen’s picture

thanks

sgurlt’s picture

I had a little problem applying the patch, the file "exposed-form-ajax.js" did not get created in "/www/sites/all/modules/contrib/views/js", instead of this is got created next to my root folder "www",
After moving the file to the correct destination the ajax problem is solved.

colan’s picture

As this is a fairly big patch, I'd like to wait for #2450447: Drupal QA is broken for Views 7.x-3.x before committing.

donquixote’s picture

It does not work for me so far with #73 based on 7.x-3.8 or more recent versions of views.
Trying to have conditional elements in a custom views field handler.

I still get "Invalid form POST data for form-...", and the AJAX response is empty.
The AJAX request has the correct form_build_id that is also found in the form html (of the field handler configuration form, not the overall views config form). But then ajax_get_form() / form_get_cache() don't find the form in the cache.
Looking into the cache_form table, the respective form_build_id is indeed not in there.

I might add more information if I have done further debugging and created a reduced example, but for now this is all I can say.

bessone’s picture

I have the same problem of @donquixote with Views 7.x-3.11 and Drupal 7.39

donquixote’s picture

There are some revealing comments in views_ui.module.

 * @see views_ui_ajax_get_form()
 */
function views_ui_edit_form($form, &$form_state, $view, $display_id = NULL) {
  // Do not allow the form to be cached, because $form_state['view'] can become
  // stale between page requests.
  // See views_ui_ajax_get_form() for how this affects #ajax.
  // @todo To remove this and allow the form to be cacheable:
  //   - Change $form_state['view'] to $form_state['temporary']['view'].
  //   - Add a #process function to initialize $form_state['temporary']['view']
  //     on cached form submissions.
  //   - Update ctools_include() to support cached forms, or else use
  //     form_load_include().
  $form_state['no_cache'] = TRUE;
/**
 * Menu callback; handles AJAX form submissions similar to ajax_form_callback(), but can be used for uncached forms.
 *
 * ajax_form_callback(), the menu callback for the system/ajax path, requires
 * the form to be retrievable from the form cache, because it lacks a trusted
 * $form_id argument with which to call drupal_retrieve_form(). When AJAX is
 * wanted on a non-cacheable form, #ajax['path'] can be set to a path whose
 * menu router item's 'page callback' is this function, and whose
 * 'page arguments' is the form id, optionally followed by additional build
 * arguments, as expected by drupal_get_form().
 *
 * The same caution must be used when defining a hook_menu() entry with this
 * page callback as is used when defining a hook_menu() entry with the
 * 'drupal_get_form' page callback: a 'page arguments' must be specified with a
 * literal value as the first argument, because $form_id determines which form
 * builder function gets called, so must be safe from user tampering.
 *
 * @see drupal_get_form()
 * @see ajax_form_callback()
 * @see http://drupal.org/node/774876
 */
function views_ui_ajax_get_form($form_id) {
donquixote’s picture

Just to mention it, in my case, I would like to implement the AJAX logic for a reusable form element, not for a specific form..

donquixote’s picture

It seems that setting ['#ajax']['path'] = $_GET['q'] is sufficient, at least for field handler config forms.

bessone’s picture

My problem is related to changes to the Ajax System introduced in Drupal 7.39 (https://www.drupal.org/drupal-7.39-release-notes), reverting back to 7.38 everything works again.

Calling ajax_set_verification_header() in the Ajax callback function didn't solve the problem.

kjl’s picture

The patch in #73 appears to have a bug in it which was revealed by the stricter form token validation in Drupal 7.39.

    if (!empty($form['#token'])) {
      $form_info['form_token'] = $form['#token'];
    }

Should probably be:

    if (!empty($form['#token'])) {
      $form_info['form_token'] = drupal_get_token($form['#token']);
    }
joelpittet’s picture

@kjl could you explain why it should be that? (Not totally familiar with the token system)

kjl’s picture

drupal_valid_token() compares form_state['values']['form_token'] (the actual token) with a hash of $form['#token'] (which is usually the form_id, not an actual token).

$form_info['form_token'] = $form['#token'];

in the patch was causing the hash of $form['#token'] to be compared to $form['#token'] itself, rather than to the token, when those values were passed to drupal_valid_token.

joelpittet’s picture

Status: Reviewed & tested by the community » Needs work

Thanks for the clarification. Setting to Needs Work with that in mind.

barraponto’s picture

Status: Needs work » Needs review
FileSize
4.17 KB

ok, re-rolled.

joelpittet’s picture

Status: Needs review » Reviewed & tested by the community

Ok since #104 was included in the re-roll in #106 I think this is fair to go back to RTBC.

jdesrig’s picture

I can confirm that patch #106 worked for me, while #73 did not. However, I am still having an issue:
I am using a country field select list to update the state field field select list. The first AJAX call works correctly and the form is rebuit, however subsequent calls do not. I have been doing some debugging and I do see that the form function is being hit again, but the State select list remains unchanged. Is this issue related to the above fix?

colan’s picture

Status: Reviewed & tested by the community » Needs review

Trying to fire up the testbot now that #2450447: Drupal QA is broken for Views 7.x-3.x is in.

colan’s picture

Status: Needs review » Active
colan’s picture

Status: Active » Needs review
colan’s picture

Status: Needs review » Reviewed & tested by the community

Sorry about the interruption. Can't test this yet as the branch is failing. Carry on.

zuernBernhard’s picture

patch #106 does not work here with Views 7.3 dev I have a View in a Panel Pane and the views exposed form outside the view-div in the panel pane template. ajax works fine (views result is replaced in the markup according to the exposed filter) but the form is not rebuild after the ajax callback (select for the exposed filter stays disabled).

colan’s picture

We've recently switched our testing from the old qa.drupal.org to DrupalCI. Because of a bug in the new system, #2623840: Views (D7) patches not being tested, older patches must be re-uploaded. On re-uploading the patch, please set the status to "Needs Review" so that the test bot will add it to its queue.

If all tests pass, change the Status back to "Reviewed & tested by the community". We'll most likely commit the patch immediately without having to go through another round of peer review.

We apologize for the trouble, and appreciate your patience.

colan’s picture

Status: Reviewed & tested by the community » Needs work
joelpittet’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
4.17 KB

Re-uploading previously RTBC'd patch from #106 for testing.

colan’s picture

Status: Reviewed & tested by the community » Postponed (maintainer needs more info)

Can someone speak to the issues raised in #108 & #113? If valid, we need to account for them.

joelpittet’s picture

@jdesrig @zuernBernhard could you provide more details so we can try to reproduce your issues? I've not run into this issue myself so far.

jncruces’s picture

FileSize
2.96 KB

I've created a module with the code of the patch #116, for use it in any case. I not publish the module because i think the patch will be applied to the original views module but this module can be used with previous version if for some reason can't be updated views.

With the patch the form become outdated i correct it with a $form['#token']=NULL;

Thanks for the patch.

mukesh4only’s picture

Thank you @jncruces

Liam Morland’s picture

University of Waterloo has successfully been using the patch in #106 since January.

kumkum29’s picture

Hello,

the views module is an important module of an site in production. For me this is a bad thing to patch directly this module.
So, I use the mini-module of #119.

Do you think include this feature / patch in the next version of views (stable or dev)?

Thanks for your replies.

riddhi.addweb’s picture

Issue tags: +Ajax, +exposed filter, +form_alter
pcambra’s picture

Just mentioning that patch in #116 solves the issue for me, exposed filter in search api with no panels.

joelpittet’s picture

Status: Postponed (maintainer needs more info) » Reviewed & tested by the community

Asked for feedback from #118 10 months ago and no feedback so setting the status again.

dww’s picture

I ran into the same problems in D8 Views trying to get #ajax working in an exposed views filter form for Address module. See #2787255: Provide a views filter for administrative areas for more. So I started porting patch #106 to D8. However, for reasons I can't explain, $form_state->getTriggeringElement() is returning the submit button, not the form element with #ajax attached. But I wanted to attach this as a start towards fixing this in D8 core. Not sure the right issue workflow for getting a Views bug like this fixed in both core (D8) and contrib (D7).

dww’s picture

I heard from dawehner in IRC that he thought a separate issue for fixing this in core for D8 views was a good idea. So I just opened #2842525: Ajax attached to Views exposed filter form does not trigger callbacks for solving this in D8 core and I'm marking that the parent issue to this one for D7 contrib.

DamienMcKenna’s picture

Rerunning the tests..

joelpittet’s picture

Status: Needs review » Reviewed & tested by the community

Other than a couple whitespace changes I spotted, this looks still RTBC and fixed the issue I was having.

GuillaumeDuveau’s picture

Hello,

I didn't review the code, but I find, too, that the patch from #129 solves the issue.

dillix’s picture

+1 for RTBC, #129 solved my issue.

Chris Charlton’s picture

That's a few RTBC yeses. :)

wdseelig’s picture

Applied the patches in 129 to Views 7.x-3.16, but Ajax still not working from exposed filters.

Not sure if these two patches alone were supposed to fix things, or whether I was supposed to apply some (all?) of the patches in the other files attached to comment 129 [Some of which failed testing?]

Took a look at views 7.x-3.17, and saw that it does not include the js file exposed-form-ajax.js, so I think I can assume that 7.x-3.17 does not include these fixes?

To be clearer about the nature of the failure: I AM getting to my ajax callback routine when I click on an element in the exposed filter. However, I am, at that point, unable to execute any ajax commands. The test code in my callback routine is as follows:

drupal_add_js('misc/ajax.js');
$commands[] = ajax_command_alert('Made it into the setindividualtags routine');
$page = array('#type' => 'ajax', '#commands' => $commands);
ajax_deliver($page);

This code works just fine in other places, but not here. Instead, I get an AJAX HTTP error with a result code of 200.

Observation: I notice in the debugging information that I get back that the Path is /system/ajax, and am wondering if I'm somehow not finding the exposed-form-ajax.js file? I have put it in both my views folder and in the views/js folder, but to no avail.

Wyckham

wdseelig’s picture

Here is the debugging information I get when I try to execute the code above:

An AJAX HTTP error occurred.
HTTP Result Code: 200
Debugging information follows.
Path: /system/ajax
StatusText: OK
ResponseText: [{"command":"settings","settings":{"basePath":"\/","pathPrefix":"","ajaxPageState":{"theme":"marinelli","theme_token":"bqgihR823xfRojqu6ZaiKNwnGWa2Mxzukr5YtPWe2YE"},"ViewsExposedFormInfo":{"field_contacttags_tid":{"form_id":"views_exposed_form","form_build_id":"form-NxLHIUooCC78UgSuIDQEAGpkLlafqKOtcOGtJ4hI3Jo"}}},"merge":true},{"command":"alert","text":"Made it into the setindividualtags routine"}][{"command":"settings","settings":{"basePath":"\/","pathPrefix":"","ajaxPageState":{"theme":"marinelli","theme_token":"bqgihR823xfRojqu6ZaiKNwnGWa2Mxzukr5YtPWe2YE"},"ViewsExposedFormInfo":{"field_contacttags_tid":{"form_id":"views_exposed_form","form_build_id":"form-NxLHIUooCC78UgSuIDQEAGpkLlafqKOtcOGtJ4hI3Jo"}}},"merge":true},{"command":"updateBuildId","old":"form-anRx-WxdIasT3TToKWVZYYwLQTBqPMybjh5aRIUmstM","new":"form-NxLHIUooCC78UgSuIDQEAGpkLlafqKOtcOGtJ4hI3Jo"}]

wdseelig’s picture

I am using Firefox developer edition to investigate this error further, and can now report the following.

When I click on an element of an exposed form, my site is, for some reason issuing the following
XMLHttpRequest (XHR):

http://(my_domain)/system/ajax

I have no idea why this is happening. When I compare this non-working code with code that successfully utilizes ajax, I see that the successfully working code issues an XHR that looks like this:

https://(mydomain)/mycallbackroutine.

In the code that works, I create a link to a menu item that goes to an ajax callback routine. In this code, I am not as free to format the item in the exposed filter, so I think I'm relying on the patched views module to do it for me.

wdseelig’s picture

I am embarrassed to have posted #134 to #136, and if I could delete them I would. I had somehow missed the need [described in Ajax forms in Drupal] to "change #ajax['path'] from the default 'system/ajax' and set up a menu entry in hook_menu to point to your replacement path." Once I did this I found that I could execute the code described in #134 just fine.

dflitner’s picture

I also am trying to implement http://bouteillenicolas.com/expertise-drupal/views-ajax-dynamic-dependen... and was getting "Invalid form POST data" and "Notice: Undefined index: form_build_id in ajax_get_form()" errors in the log. The patch in #129 fixed it for me and ajax now works as desired in my exposed filter.

Views 7.x-3.18.

tucho’s picture

The patch at #129 works for me too.

I have written an drupal_form_alter to attach the AJAX hook and I have tested it with Drupal 7.56 and Views 3.18.

omnia.ibrahim’s picture

Rajeev H’s picture

The patch views-n1183418-128.patch works fine.

pbirk’s picture

Confirming patch views-n1183418-128.patch works against Views 7.x-3.20.

I verified after a fresh download of Views 7.x-3.20 my callback did not fire after modifying the select field it was attached to. Applied patch and the callback fired as expected.

Thanks @DamienMcKenna!

sano’s picture

Patch #140 works for me as well. Views 7.x-3.20. Thank you all.

pbirk’s picture

Tested #129 no longer works for my site against the latest development branch. I haven't attempted to troubleshoot that yet and likely won't manage to this week.

DamienMcKenna’s picture

DamienMcKenna’s picture

Use struct on the JS, which necessitated changing the comparison statement to an equality operator. Can someone please test it? Thanks.

Status: Needs review » Needs work

The last submitted patch, 146: views-n1183418-146.patch, failed testing. View results

DamienMcKenna’s picture

Status: Needs work » Needs review
sano’s picture

Status: Needs review » Reviewed & tested by the community

I installed a fresh copy of views 7.x-3.20 and run my app. Saw JS error whenever trying to set a checkbox value in my ajax-interconnected exposed filters. Corresponding log entry:

Notice: Undefined index: form_build_id in ajax_get_form() (line 325 of .../includes/ajax.inc).

After applying the patch my exposed filter works and I have no entries in the log. Thank you.

pbirk’s picture

Finally dug into this more and found my site broke due an unrelated Views patch that I missed installing after updating. Turns out my site works after updating to Views 7.x-3.20+29-dev both with and without the patch from #146. While I can't confirm the patch fixed anything, I can confirm nothing new appears broken on my site.

sano’s picture

just updated views to v. 7.x-3.21 and the patch is still necessary & applies cleanly.

pbirk’s picture

I just upgraded my site to 7.x-3.22 and found I was able to reproduce errors related to this again. The patch from #146 installed cleanly and resolved the errors.

I also decided to test this against 7.x-3.22+51-dev and found the patch applied, but not perfectly cleanly. It created a views.module.orig file. I'm attaching an updated patch against that branch. I don't think anything changed but the line number references.

DamienMcKenna’s picture

Status: Reviewed & tested by the community » Needs work

@pbirk: thanks for the reroll.

This needs a tiny improvement with the comments, e.g. this comment is unfinished:

+ * @param array $form_state
+ *   The 
Liam Morland’s picture

Re-roll with comments updated and array type declarations added.

pbirk’s picture

Status: Needs review » Reviewed & tested by the community

Marking RTBC. Tested patch in #154 against views-3.x-dev. Comments appear complete now.

DamienMcKenna’s picture

Status: Reviewed & tested by the community » Fixed
Parent issue: » #3054023: Plan for Views 7.x-3.24 release

Committed. Thanks everyone!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.