| Project: | Views |
| Version: | 7.x-3.x-dev |
| Component: | exposed filters |
| Category: | bug report |
| Priority: | major |
| Assigned: | Unassigned |
| Status: | needs work |
| Issue tags: | exposed filter |
Issue Summary
I have some fields exposed in filter criteria, and my exposed form style is input required.
So as expected, when i visit the view path i see only the exposed form and no results from the view, until i submit (or apply the filters). What i don't want is to be able to submit an empty form and see all the results from my view, so i check the fields i need to have a value as required but they automatically receive an .error class (so they get a red margin) before i apply the filters (or submit). I would like to have this validation after the form is submitted not before, since, in my understanding, the whole meaning of having input required is to wait for the filters to be applied (and maybe do some validation if something is marked as required) then show results.
This also happens when the form is exposed in a block.
What i wanted is to have my filters exposed in a block and loaded in a region on my home page, then submit the form and see the results in my view. It works as expected with this one little drawback, the required fields in the exposed form receive the .error class before the form is submitted even though the validation should be done after submission
Comments
#1
facing the same problem and not sure if to simply override it using js or dive deeper into the module (which might end up consuming hell lot of time)
#2
facing the same problem and not sure if to simply override it using js or dive deeper into the module (which might end up consuming hell lot of time)
#3
Well the only hint i have is in
sites/all/modules/views/plugins/views_plugin_exposed_form.inc line 151 in function render_exposed_form
its using this function to build the form, $form = drupal_build_form('views_exposed_form', $form_state);
and drupal_build_form does the processing, validation and submission all in one go (from here
http://api.drupal.org/api/drupal/includes!form.inc/function/drupal_build_form/7 )
On the other hand, when you build forms in a module you can just use drupal_get_form, and provide the function that builds the render array to it. Then have a _validate function and it runs as expected, you get the form, and on submission it's validated (also shows validation error messages if it doesn't pass). Example here
http://codekarate.com/daily-dose-of-drupal/drupal-7-module-development-p...
#4
Hi, have the same issue, don't know how to fix this, but this definitely needs some work, because this behavior is incorrect.
#5
Bug confirmed in views-7.x-3.5+37-dev on two separate websites using required exposed textfields and the "exposed form style" set to either "input required" or "basic".
Here's a simple view to test it:
<?php
$view = new view();
$view->name = 'exposed_test';
$view->description = '';
$view->tag = 'default';
$view->base_table = 'node';
$view->human_name = 'Exposed test';
$view->core = 7;
$view->api_version = '3.0';
$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
/* Display: Master */
$handler = $view->new_display('default', 'Master', 'default');
$handler->display->display_options['title'] = 'Exposed test';
$handler->display->display_options['use_more_always'] = FALSE;
$handler->display->display_options['access']['type'] = 'perm';
$handler->display->display_options['cache']['type'] = 'none';
$handler->display->display_options['query']['type'] = 'views_query';
$handler->display->display_options['exposed_form']['type'] = 'basic';
$handler->display->display_options['pager']['type'] = 'full';
$handler->display->display_options['pager']['options']['items_per_page'] = '10';
$handler->display->display_options['style_plugin'] = 'default';
$handler->display->display_options['row_plugin'] = 'node';
/* Field: Content: Title */
$handler->display->display_options['fields']['title']['id'] = 'title';
$handler->display->display_options['fields']['title']['table'] = 'node';
$handler->display->display_options['fields']['title']['field'] = 'title';
$handler->display->display_options['fields']['title']['label'] = '';
$handler->display->display_options['fields']['title']['alter']['word_boundary'] = FALSE;
$handler->display->display_options['fields']['title']['alter']['ellipsis'] = FALSE;
/* Filter criterion: Content: Title */
$handler->display->display_options['filters']['title']['id'] = 'title';
$handler->display->display_options['filters']['title']['table'] = 'node';
$handler->display->display_options['filters']['title']['field'] = 'title';
$handler->display->display_options['filters']['title']['operator'] = 'contains';
$handler->display->display_options['filters']['title']['exposed'] = TRUE;
$handler->display->display_options['filters']['title']['expose']['operator_id'] = 'title_op';
$handler->display->display_options['filters']['title']['expose']['label'] = 'Title';
$handler->display->display_options['filters']['title']['expose']['operator'] = 'title_op';
$handler->display->display_options['filters']['title']['expose']['identifier'] = 'title';
$handler->display->display_options['filters']['title']['expose']['required'] = TRUE;
$handler->display->display_options['filters']['title']['expose']['remember_roles'] = array(
2 => '2',
1 => 0,
3 => 0,
);
/* Display: Page */
$handler = $view->new_display('page', 'Page', 'page');
$handler->display->display_options['defaults']['hide_admin_links'] = FALSE;
$handler->display->display_options['path'] = 'exposed-test';
$handler->display->display_options['menu']['type'] = 'normal';
$handler->display->display_options['menu']['title'] = 'Exposed';
$handler->display->display_options['menu']['weight'] = '0';
$handler->display->display_options['menu']['context'] = 0;
$handler->display->display_options['tab_options']['weight'] = '0';
?>
#6
The error class was introduced in Drupal 7.17. I managed to trace it to this patch in form.inc.
Here's the (reopened) issue: #1785436: Submission of #required elements without #title and empty value does not display any error
#7
(semi-crosspost with #1785436: Submission of #required elements without #title and empty value does not display any error #22)
Hmmm... Further investigation points to this piece of code in
views/plugins/views_plugin_exposed_form.inc->render_exposed_form()<?php
$form_state = array(
'view' => &$this->view,
'display' => &$this->display,
'method' => 'get',
'rerender' => TRUE,
'no_redirect' => TRUE,
'always_process' => TRUE,
);
...
$form_state['exposed_form_plugin'] = $this;
$form = drupal_build_form('views_exposed_form', $form_state);
$output = drupal_render($form);
?>
In this case
'always_process' => TRUEtriggers form validation, which < Drupal 7.17 did throw an error(!), but without the error class. I now believe the patch from this issue reveiled the error in the views exposed filter plugin instead of causing it ...The attached patch only processes the form if there actually is input. This seems to be a really straight-forward fix for a long time error which became visible with the fix in Drupal 7.17, but it also changes the way you have to set default values for exposed filters.
Before the patch:
<?phpif (!isset($form_state['view']->exposed_input['my_field'])) {
$form_state['input']['my_field'] = 'my value';
}
?>
after the patch:
<?php$form['my_field']['#default_value'] = 'my value';
?>
You now can omit the
if ()because'always_process'is triggered when there's input available from $_GET (or session, etc) and will override whatever you set as default value with the input.Bumping it to 'major' since a lot of websites will encounter this bug/misbehaviour when updating to Drupal 7.17+.
#8
Note to self: do not only check if you've actually attached the patch, also check if you set the status to 'needs review' ;)
#9
The last submitted patch, 1877678_views_plugin_exposed_form_check_input.patch, failed testing.
#10
Not only did my patch fail testing, it's also not good enough.
I only check if there's input, not if the input matches the exposed filters in this view. This means that all forms are processed when there's input and the error class returns for all exposed filters on that page.
This also explains this function in
views_plugin_exposed_form_input_required.inc<?php
function exposed_filter_applied() {
static $cache = NULL;
if (!isset($cache)) {
$view = $this->view;
if (is_array($view->filter) && count($view->filter)) {
foreach ($view->filter as $filter_id => $filter) {
if ($filter->is_exposed()) {
$identifier = $filter->options['expose']['identifier'];
if (isset($view->exposed_input[$identifier])) {
$cache = TRUE;
return $cache;
}
}
}
}
$cache = FALSE;
}
return $cache;
}
?>
A revisited patch will probably move that function into
views_plugin_exposed_form.incand use it instead of$exposed_input = $this->view->get_exposed_input();#11
Here's the revised patch which moves
get_exposed_input()into theviews_plugin_exposed_formclass. I had to get rid of the static cache because it had to be cached for each identifier.Really hoping someone looks into this ...
#12
The last submitted patch, 1877678_views_plugin_exposed_form_check_input_2.patch, failed testing.
#13
Changing the title to reflect the problem. Still hoping someone looks into this.
#14
#11: 1877678_views_plugin_exposed_form_check_input_2.patch queued for re-testing.
#15
The last submitted patch, 1877678_views_plugin_exposed_form_check_input_2.patch, failed testing.