Hi guys!
How to reproduce:
Create a view with at least an exposed taxonomy filter ('Content: Has taxonomy term').
Configure the exposed form settings to expose also the "reset button" ( or not ;-).
Select one term and hit "Apply".
By going to the actual url of the view (not the editing page) everything work as expected but not in the preview, where the results are the same (like if the filtes weren't be applied).
Trying to address the issue i realize that ctools_object_cache_get is going be to called (view_ui.module line 265 approx.) and that function has been marked as Deprecated, also that in views_ui_preview (admin.inc line 87 approx.) the $exposed_input variable (conceptually the user's input on the filter ) is build from $exposed_input = $_POST and it's empty also when a filter option is selected, is this the normal behavior?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

dawehner’s picture

I was so sure, that i filled an issue already, but you provided some helpful informations.

neoglez’s picture

Assigned: Unassigned » neoglez

I'm gonna try to deal with this...(or souldn't i? ;-)

dawehner’s picture

If you manage to fix the issue, it would be cool.

This worked one time, you could use git bisect with the commit of the new ui as start.

neoglez’s picture

Title: Taxonomy exposed filters not being applied in Preview » Exposed filters not being applied in Preview

Tested with other Filters (e.g. Content: Published)--> the same situation.

neoglez’s picture

Well, this issues are caused by the separation of the forms in the preview, one containig the checkbox 'Auto preview' and the textbox 'Preview with contextual filters' (FAPI ID views_ui_edit_form) and the otherone the exposed filters + preview results (FAPI ID views_ui_edit_form), there also some comments and @todo in the code related to this.
All exposed input is gadered in admin.inc

 118  // AJAX happens via $_POST but everything expects exposed data to
 119   // be in GET. Copy stuff but remove ajax-framework specific keys.
 120  $exposed_input = $_POST;

First of all it's clear that is not gonna work for non-JS users since the form containig the exposed filters has the method set to get (views_plugin_exposed_form.inc line 117), $_POST is empty when submiting the form, this no happening in the 'normal page' (not preview) becouse the the request is handle by a different callback.
On the other hand the approach to JS-users also fails becouse when clicking the 'Apply' or 'Reset' button the click on the 'Update preview' button is triggered (via ajax) submiting the form views_ui_edit_form and not views_ui_edit_form, wich contains the exposed filters, the 'normal page' works here becouse differents js files are included depending on the situatuion (ajax.js for views ui in contrast to ajax_view.js in the normal page), this is the good news ;-)
Well, here is a solution althoug i think a more consistent approach could be developed.

  1. Remove the ajax behavior of the Apply button (we'll do it with FAPI) in ajax.js, leave the reset (not so consistent:-(
  2.       // Within a live preview, make exposed widget form buttons re-trigger the
          // Preview button.
          // @todo Revisit this after fixing Views UI to display a Preview outside
          //   of the main Edit form.
     182   - $('div#views-live-preview input[type=submit]')
        
          // Within a live preview, make exposed widget form buttons re-trigger the
          // Preview button.
          // @todo Revisit this after fixing Views UI to display a Preview outside
          //   of the main Edit form.
    182    + $('div#views-live-preview #edit-reset')
       
  3. Add the ajax behavior to the Apply button in views_plugin_exposed_form.inc
  4.     $form_state['pager_plugin'] = $pager;
      }
    236 +  // If we are in live preview give the buttons ajax behavior, if not do nothing,
          +  // views_ajax takes care.
          +  if (isset($this->view->live_preview) && $this->view->live_preview == TRUE)  {
          +      $q = 'admin/structure/views/view/' . $this->view->name . '/preview/' . $this->view->current_display . '/ajax';
          +      $form['submit']['#ajax']  =  array (
          +          'path' => (!empty ($this->view->args)) ? $q . '/' . implode('/', $this->view->args) : $q,
          +          'wrapper' => 'views-preview-wrapper',
          +          'event' => 'click',
          +          'progress' => array('type' => 'throbber'),
          +          'method' => 'replace',
          +      );
          + }
    
  5. Now both forms are passing throug views_ui_build_preview in admin.inc -> attempt to discriminate between them and handle contextual filters and exposed filters input mapping them to the right variables.
  6.   $build = array(
        '#theme_wrappers' => array('container'),
        '#attributes' => array('id' => 'views-preview-wrapper', 'class' => 'views-admin clearfix'),
      );
    895 + if (!isset($_POST['form_id'])  ||  ($_POST['form_id'] != 'views_ui_preview_form')) {
          +     $_POST['view_args'] = implode('/', array_slice(func_get_args(), 2));
          + }
    
  7. Adjusting the way the exposed input is handle in admin.inc function views_ui_preview , since there are now two forms $_POST could contain contextual filters and no more (e.g. the user enters a parameter and click 'Update preview'). Also remove the 'hack', (no such a variables in $exposed_input), but leave the form_id for consistency.
  8.           // AJAX happens via $_POST but everything expects exposed data to
              // be in GET. Copy stuff but remove ajax-framework specific keys.
     120     - $exposed_input = $_POST;
     120     + // If the user is updating the preview to incorporate parameters (contextual filters)
               + // DON'T asume the exposed input come from $_POST, just live the exposed_input empty
               + if (empty($_POST) || (isset($_POST['form_id']) && $_POST['form_id'] == 'views_ui_preview_form')) {
               +     $exposed_input = array();
               + }
               + else {
               +     // $exposed_input is comming from $_POST
               +     $exposed_input = $_POST;
               + }
    
    126    - // @todo Remove this hack after fixing Views UI to display the preview
             - //   outside of the edit form, so that the edit form doesn't conflict with
             - //   the exposed widget form.
               $exposed_input['form_id'] = 'views_exposed_form';
             - unset($exposed_input['form_build_id'], $exposed_input['form_token']);
    
  9. Also we have to add the default value to the 'Update preview' form element ('Apply' refresh the whole container).
  10. 1146  -  //      '#attributes' => array('class' => array('ctools-auto-submit')),
            +  '#default_value' => $form_state['input']['view_args'],
    
  11. Finally, in view.inc function get_exposed_input, this is important for non-JS users
            // Fill our input either from $_GET or from something previously set on the
            // view.
    199   + if (!isset($this->exposed_input) || empty ($this->exposed_input)) {
            +    $this->exposed_input['form_id'] = 'views_exposed_form'; 
            + }
    
            -   if (empty($this->exposed_input)) {
            -       $this->exposed_input = $_GET;
    
            +   if (count($this->exposed_input == 1) ) {
            +      $this->exposed_input += $_GET;
    
dawehner’s picture

Can you please always create a .patch file? It's much easier to test it and perhaps with dreditor also to review.

neoglez’s picture

neoglez’s picture

Status: Active » Needs review
neoglez’s picture

Fixing an undefined index in the first run.

merlinofchaos’s picture

Status: Needs review » Needs work

#9 violates code style with inconsistent tabbing.

jpstrikesback’s picture

Status: Needs work » Needs review
FileSize
4.64 KB

Thanks neoglez! :)

Rerolled to latest dev and added one fix - func_get_Args() doesn't like being a parameter to another function prior to 5.3 - quote below:

Because this function depends on the current scope to determine parameter details, it cannot be used as a function parameter in versions prior to 5.3.0. If this value must be passed, the results should be assigned to a variable, and that variable should be passed.

dawehner’s picture

Status: Needs review » Needs work
+++ b/includes/admin.incundefined
@@ -117,7 +117,16 @@ function views_ui_preview($view, $display_id, $args = array()) {
+    if (empty($_POST) || (isset($_POST['form_id']) && $_POST['form_id'] == 'views_ui_preview_form')) {
+        $exposed_input = array();
+    }
+    else {
+        $exposed_input = $_POST;

Drupal uses 2 spaces here.

+++ b/includes/admin.incundefined
@@ -127,7 +136,6 @@ function views_ui_preview($view, $display_id, $args = array()) {
-    unset($exposed_input['form_build_id'], $exposed_input['form_token']);

What is the reason to remove it?

+++ b/includes/admin.incundefined
@@ -909,6 +917,11 @@ function views_ui_build_preview($view, $display_id) {
+  if (!isset($_POST['form_id']) || ($_POST['form_id'] != 'views_ui_preview_form')) {
+    $args = func_get_args();
+    $_POST['view_args'] = implode('/', array_slice($args, 2));

A comment would be cool here

+++ b/includes/view.incundefined
@@ -203,8 +203,12 @@ class view extends views_db_object {
-      $this->exposed_input = $_GET;
+    if (!isset($this->exposed_input) || empty($this->exposed_input)) {
+      $this->exposed_input['form_id'] = 'views_exposed_form';
+    }
+
+    if (count($this->exposed_input) == 1) {
+      $this->exposed_input += $_GET;
       // unset items that are definitely not our input:
       foreach (array('page', 'q') as $key) {
         if (isset($this->exposed_input[$key])) {
diff --git a/js/ajax.js b/js/ajax.js

diff --git a/js/ajax.js b/js/ajax.js
index 001a9d3..eb730c5 100644

index 001a9d3..eb730c5 100644
--- a/js/ajax.js

--- a/js/ajax.js
+++ b/js/ajax.jsundefined

+++ b/js/ajax.jsundefined
+++ b/js/ajax.jsundefined
@@ -179,7 +179,7 @@

@@ -179,7 +179,7 @@
       // Preview button.
       // @todo Revisit this after fixing Views UI to display a Preview outside
       //   of the main Edit form.
-      $('div#views-live-preview input[type=submit]')
+      $('div#views-live-preview #edit-reset')
         .once('views-ajax-processed').each(function () {
         $(this).click(function(event) {
           event.preventDefault();
diff --git a/plugins/views_plugin_exposed_form.inc b/plugins/views_plugin_exposed_form.inc

diff --git a/plugins/views_plugin_exposed_form.inc b/plugins/views_plugin_exposed_form.inc
index 1a08fa6..ed65d5c 100644

index 1a08fa6..ed65d5c 100644
--- a/plugins/views_plugin_exposed_form.inc

--- a/plugins/views_plugin_exposed_form.inc
+++ b/plugins/views_plugin_exposed_form.incundefined

+++ b/plugins/views_plugin_exposed_form.incundefined
+++ b/plugins/views_plugin_exposed_form.incundefined
@@ -233,6 +233,18 @@ class views_plugin_exposed_form extends views_plugin {

@@ -233,6 +233,18 @@ class views_plugin_exposed_form extends views_plugin {
       $form_state['pager_plugin'] = $pager;
     }
 
+    //If we are in live preview give the button ajax behavior, if not do nothing,
+    //views_ajax.js takes care
+    if(isset($this->view->live_preview) && $this->view->live_preview == TRUE) {
+      $q = 'admin/structure/views/view/' . $this->view->name . '/preview/' . $this->view->current_display . '/ajax';
+      $form['submit']['#ajax'] = array(
+        'path' => (!empty($this->view->args)) ? $q . '/' . implode('/', $this->view->args) : $q,
+        'wrapper' => 'views-preview-wrapper',
+        'event' => 'click',
+        'progress' => array('type' => 'throbber'),
+        'method' => 'replace',
+      );
+    }
 
     // Apply autosubmit values.
     if (!empty($this->options['autosubmit'])) {

!isset is also empty, so why is here a check for both?

Powered by Dreditor.

jpstrikesback’s picture

As i didn't create the original I can't answer all too quick but i'll try as time permits:

1) patch attached
2) seems to be cruft from an old approach, removed entirely in attached patch (for some history see commit 660c523b0eb0768034f336171af321873fc52cce)
3) Neoglez?
4) Neoglez?

Cheers
JP

neoglez’s picture

Let's see, i was testing this patch (#9) and it doesn't work pretty well (apart of the formating thing) -and for you?
Before let's try to agree in the logic (in a simplified flow):
There are two FORMS: one $_POST (views_ui_edit_form) and one $_GET (views_ui_edit_form)

  1. The user build the view, introduce arguments and click 'update preview'- only the content of the textfield is sent to the server.
  2. What happens actually is that arguments are appended to the url of the $_GET form.

  3. The user wants to test the exposed filters and now clicks 'apply' - all the info in exposed filters is sent to the server (here there is a problem with #9 for JS users becouse the whole container is refreshed so parameters of the $_POST form are lost)

Question:
Shoud we nice degradate when no-JS-preview? I would say yes. At the momment views only degradate (but not so nice e.g. only the preview is rendered but not the view-edit-form)

Drupal uses 2 spaces here.

OK.

What is the reason to remove it?

Now the information comes separately, there is no need to do it becouse those values are beeing posted only when clicking 'update preview' and in this case we want them (why shoudn't we?), if 'Apply' is clicked then this values are not posted (why attempt to remove them if they don't exist).

A comment would be cool here

What about something like:

// There are two form information passing through this function:
// views_ui_edit_form and views_ui_edit_form, 
// attempt to descriminate between them.
!isset is also empty, so why is here a check for both?

Good catch!
Thanks guys for the review!!

neoglez’s picture

@jpstrikesback, we're almost there ;-)
Did you try the patch and realize 2. of #14??
Thanks!

merlinofchaos’s picture

Priority: Normal » Major
Status: Needs work » Needs review
FileSize
3.42 KB

Ok, restarted this from scratch, now that I understand.

Also, the way we reset was broken, so I had to fix it to get the reset button to work as well. This patch preserves interaction with summary arguments as well, unlike the earlier patches.

I think this is ready to go as is but I would like a couple of independent tests.

merlinofchaos’s picture

This patch actually ends up demonstrating that reset doesn't work with use_ajax, so that probably has to be fixed as well, but it does not need to be fixed as part of this patch.

neoglez’s picture

Status: Needs review » Reviewed & tested by the community

Patch #16 seems to be working very well (NOT the reset, we would have to file an issue report for this one) and compliant with the logic in #14.
It also degradates (like before said NOT nice) for non-JS users.
I say we commit it.

neoglez’s picture

Assigned: neoglez » Unassigned

;-)

jpstrikesback’s picture

Tested, works, reset get's all funny as expected (once I add multiple exposed filters).

One thing I noticed (that may be to do with the filter handler I'm trying to build) was that when there was a sql error dependencies stopped working...but that would be something separate I think...

merlinofchaos’s picture

Status: Reviewed & tested by the community » Fixed

Thanks!

Committed the patch. We need a separate issue for the reset button. Can you post one with what you saw with reset? i'm not sure what all the problems are going to be, as I didn't delve too deeply. I made sure the very basic reset routine worked and that was it.

neoglez’s picture

Status: Fixed » Closed (fixed)

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