I need to hide the pager's exposed options (results per page) when the view has no results. I looked everywhere but can't find anything.
Thanks
I need to hide the pager's exposed options (results per page) when the view has no results. I looked everywhere but can't find anything.
Thanks
There is no intuitive way to do it, but I found a solution using hook_views_post_execute
and hook_form_views_exposed_form_alter
:
function MYMODULE_views_post_execute(&$view) {
if ($view->name == 'MY-VIEW-NAME') {
// Regenerate the exposed form after execute the view query
$exposed_form = $view->display_handler->get_plugin('exposed_form');
$view->exposed_widgets = $exposed_form->render_exposed_form();
}
}
function MYMODULE_form_views_exposed_form_alter(&$form, &$form_state) {
$view = &$form_state['view'];
if ($view->name == 'MY-VIEW-NAME') {
if ($view->total_rows == 0) {
// Hide 'results per page' when the view has no results.
$form['items_per_page']['#access'] = FALSE;
}
}
}
Copy 'sites/all/modules/views/theme/views-exposed-form.tpl.php' file in your custom theme folder and modify this section:
<?php if (!empty($items_per_page)): ?>
<div class="views-exposed-widget views-widget-per-page">
<?php print $items_per_page; ?>
</div>
<?php endif; ?>
However, this is the exposed filters form, so you don't have any results to work with. You'll have to build a basic query and test if there are entries in the database.
Turns out the answer to this depends on whether you have other exposed form elements that you want to be shown when there are no results.
If you do have other exposed form elements, use smartinm's solution on this page, which preserves the submit button, surrounding markup, and other elements if there are any.
FREE BONUS: If you'd also like to not show options that wouldn't do anything because there aren't enough results, use this code below. (for example, with this, if your options are 15, 30, 45, All, then this will show just 15, 30 and All if there are 32 results, and only 'All' if there are 3 results). This is a good UX practice - you're not giving the user broken buttons or the misleading impression there are more results when there aren't, and also, if all results are being shown, it tells them so:
function MYMODULE_views_post_execute(&$view) {
if ($view->name == 'MY-VIEW-NAME') {
// Regenerate the exposed form after execute the view query
$exposed_form = $view->display_handler->get_plugin('exposed_form');
$view->exposed_widgets = $exposed_form->render_exposed_form();
}
}
function MYMODULE_form_views_exposed_form_alter(&$form, &$form_state) {
$view = &$form_state['view'];
if ($view->name == 'MY-VIEW-NAME') {
if ($view->total_rows == 0) {
// Hide 'results per page' when the view has no results.
$form['items_per_page']['#access'] = FALSE;
} else {
foreach($form['items_per_page']['#options'] as $index => $string) {
$results_option = (int)($string);
if( $results_option > $view->total_rows ) {
// Don't offer to show X results if there are <X results to show
if (isset($_GET['items_per_page']) && (string)$_GET['items_per_page'] == (string)$results_option ) {
// Prevent "An illegal choice has been detected" error, don't show meaningless selection in UI
unset($_GET['items_per_page']);
} else {
unset( $form['items_per_page']['#options'][$index] );
}
}
}
}
}
}
If you don't have any other (non-pager) exposed form elements, then that other code will leave markup and submit buttons that don't do anything. Use something simpler like this which removes the entire form, including submit button and surrounding markup (tested on a setup showing the view as a context view in ctools page manager, results in other setups may vary):
function MYMODULE_views_post_execute(&$view) {
if ($view->name == 'MYVIEW') {
if ($view->total_rows == 0) {
unset( $view->exposed_widgets );
}
}
}
FREE BONUS: If you'd also like to not show options that wouldn't do anything because there aren't enough results (see above), use this:
function MYMODULE_views_post_execute(&$view) {
if ($view->name == 'MYVIEW') {
if ($view->total_rows == 0) {
unset( $view->exposed_widgets );
} else {
// Regenerate the exposed form after execute the view query
$exposed_form = $view->display_handler->get_plugin('exposed_form');
$view->exposed_widgets = $exposed_form->render_exposed_form();
}
}
}
function MYMODULE_form_views_exposed_form_alter(&$form, &$form_state) {
$view = &$form_state['view'];
if ($view->name == 'MYVIEW' && $view->total_rows > 0 ) {
foreach($form['items_per_page']['#options'] as $index => $string) {
$results_option = (int)($string);
if( $results_option > $view->total_rows ) {
// Don't offer to show X results if there are <X results to show
if (isset($_GET['items_per_page']) && (string)$_GET['items_per_page'] == (string)$results_option ) {
// Prevent "An illegal choice has been detected" error, don't show meaningless selection in UI
unset($_GET['items_per_page']);
} else {
unset( $form['items_per_page']['#options'][$index] );
}
}
}
}
}
There might be a way to use one set of code for both: loading the form array in _views_post_execute()
somehow, pumping the form contents through element_children()
and counting to see if there are any elements other than items_per_page, submit, etc - removing the whole form if there aren't. I couldn't find anything simple however, also, anything based on that would break if there were any changes to the number of standard elements in an exposed form. Simply removing the submit doesn't work - it leaves all the empty markup for the form.
I ended up hiding it with css and showing it with javascript in case the view returned something.
This way no further server processing is required and is easier to maintain.