6

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

2
  • 1
    @ Marius - hope you don't mind me promoting and adding info to your question, there really does seem to be nothing on this topic and it's a real pain. Did you find anything that worked since asking in August? Commented Nov 7, 2012 at 19:01
  • unfortunately not :( I ended up hiding it with javascript Commented Nov 7, 2012 at 19:32

4 Answers 4

6
+50

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;
    }
  }
} 
2
  • Hmm, nearly there. Only problem is, for me (using a page manager/panels display), the 'Apply' button still renders. Any ideas? Will see if I can find a fix. Commented Nov 12, 2012 at 11:41
  • I think I've figured it out - your code works if there are other exposed form elements, but not so well if there are none. I've adapted your code below to have a variant that works in each case. I'm going to test some more, bounty on its way for you assuming this is all correct. Commented Nov 12, 2012 at 12:35
3

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.

2

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.

0

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.