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?

Files: 
CommentFileSizeAuthor
#73 views-exposed_forms_ajax_support-1183418-73.patch4.15 KBjonhattan
PASSED: [[SimpleTest]]: [MySQL] 1,658 pass(es).
[ View ]
#46 views-exposed_forms_ajax_support-1183418-46.patch4.23 KBInternetDevels
PASSED: [[SimpleTest]]: [MySQL] 1,627 pass(es).
[ View ]
#45 views-exposed_forms_ajax_support-1183418-45.patch4.29 KBInternetDevels
PASSED: [[SimpleTest]]: [MySQL] 1,627 pass(es).
[ View ]
#41 views-exposed_forms_ajax_support-1183418-41.patch2.98 KBInternetDevels
PASSED: [[SimpleTest]]: [MySQL] 1,603 pass(es).
[ View ]
#37 views-exposed_forms_ajax_support-1183418-37.patch2.46 KByannickoo
PASSED: [[SimpleTest]]: [MySQL] 1,603 pass(es).
[ View ]
#33 views-exposed_forms_ajax_support-1183418-33.patch2.46 KByannickoo
PASSED: [[SimpleTest]]: [MySQL] 1,603 pass(es).
[ View ]
#31 views-exposed-forms-ajax-support-1183418-32.patch2.46 KBbarraponto
Test request sent.
[ View ]
#30 views-exposed-forms-ajax-support-1183418-30.patch2.34 KBbarraponto
Test request sent.
[ View ]
#28 views-exposed-forms-ajax-support-1183418-28.patch2.32 KBbarraponto
FAILED: [[SimpleTest]]: [MySQL] 1,579 pass(es), 24 fail(s), and 0 exception(s).
[ View ]
#26 views-exposed-forms-ajax-support-1183418-26.patch2.32 KBbarraponto
FAILED: [[SimpleTest]]: [MySQL] 1,603 pass(es), 0 fail(s), and 25 exception(s).
[ View ]

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:

<?php
$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:

<?php
$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():

<?php
/* 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:

<?php
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":

<?php
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().

<?php
/**
 * 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
StatusFileSize
new2.32 KB
FAILED: [[SimpleTest]]: [MySQL] 1,603 pass(es), 0 fail(s), and 25 exception(s).
[ View ]

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
StatusFileSize
new2.32 KB
FAILED: [[SimpleTest]]: [MySQL] 1,579 pass(es), 24 fail(s), and 0 exception(s).
[ View ]

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
StatusFileSize
new2.34 KB
Test request sent.
[ View ]

keep posting the wrong patch...

barraponto’s picture

StatusFileSize
new2.46 KB
Test request sent.
[ View ]

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

StatusFileSize
new2.46 KB
PASSED: [[SimpleTest]]: [MySQL] 1,603 pass(es).
[ View ]

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
StatusFileSize
new2.46 KB
PASSED: [[SimpleTest]]: [MySQL] 1,603 pass(es).
[ View ]

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 Duo’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
StatusFileSize
new2.98 KB
PASSED: [[SimpleTest]]: [MySQL] 1,603 pass(es).
[ View ]

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!

jucallme’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
StatusFileSize
new4.29 KB
PASSED: [[SimpleTest]]: [MySQL] 1,627 pass(es).
[ View ]

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

InternetDevels’s picture

StatusFileSize
new4.23 KB
PASSED: [[SimpleTest]]: [MySQL] 1,627 pass(es).
[ View ]

Forgot to remove console.log from js.

jucallme’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?

jucallme’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.

jucallme’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.

jucallme’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

StatusFileSize
new28.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

<?php
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

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

To

<?php
  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

Issue summary:View changes
StatusFileSize
new3.31 KB
PASSED: [[SimpleTest]]: [MySQL] 1,658 pass(es).
[ View ]

ET voilà

jonhattan’s picture

StatusFileSize
new4.15 KB
PASSED: [[SimpleTest]]: [MySQL] 1,658 pass(es).
[ View ]

#72 is missing file js/exposed-form-ajax.js. Rerolled.

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.

tilon’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.