There is a (Views2) view listing any type of elements and with at least one exposed filter. The task is to show the empty text instead of the list if the filter is not set. One part of the solution can be found at forum, but is not perfect. It works fine while every part of the exposed filters are textfields - but there are views with optional filters shown as dropdowns/selects with the first, "empty" element being <All>. This value is being sent to PHP as All, so the array checked in the above code will not be empty, so the list will appear when one of the exposed filters was shown as dropdown/select, and was optional. Here is a solution which works fine even in such cases.

  1. Add a Global: Null argument at view edit cockpit.
  2. Set Action to take if argument is not present to Provide default argument.
  3. Set Default argument type to Fixed entry and leave textarea empty.
  4. Choose PHP Code from the Validator dropdown and new textarea will show up.
  5. Copy this code to the PHP validate code textarea (without the <?php and ?>):
    $is_filtered = FALSE;
    foreach ($view->filter as $filter) {
      if ($filter->options['exposed']) {
        if (!empty($view->display[$view->current_display]->handler->handlers['filter'][$filter->options['id']]->value)) {
          $is_filtered = TRUE;
          break;
        }
      }
    }
    return $is_filtered; 
  6. Set Action to take if argument does not validate dropdown to Display empty text.
  7. Set a value for Empty text in the main views dialog, for example this (with input-type = PHP code):
    
    $view = views_get_current_view();
      if (count($view->exposed_input)) {
        return "Sorry, no results were found.  Please adjust your search criteria and try again.";
    }
    

Some explanations for the pros: the above code iterates through all the filters attached to the view, and when it finds an exposed one, it checks whether the filter's condition is set in the view's actual display. This approach adds one tiny bit to the above-mentioned one: it works fine as expected with optional, exposed filters shown as dropdowns/selects - additionally it handles the case when a the user/browser gets a field with a different name than it's real name (eg. the node's title is a person's name, so it was renamed from title to name.)

Comments

mjanouch’s picture

I think that instead of

$filter->options['field']

should be

$filter->options['id']

because if there are, for example, two taxonomy filters, the field option is the same for them (tid) and the value will be always from the first one - so we'll never check the second taxonomy filter.

hansrossel’s picture

This is correct and I changed it in the code. With $filter->options['field'] one of my exposed filters did not work anymore.

Samshel’s picture

When you use the filter with the between operator, you don't get a single value with

$view->display[$view->current_display]->handler->handlers['filter'][$filter->options['id']]->value

Instead you get an array.

//When the filter is empty it looks like this
Array
(
    [value] => 
    [min] => 
    [max] => 
)

//When the filter has data it looks like this
Array
(
    [min] => 2010-08-01 00:00:00
    [max] => 2010-08-18 00:00:00
    [default_date] => 
    [default_to_date] => 
)

So using your solution I just changed the conditional so it validates if one of them has data to return values, since having min or max values alone works too.

 if (!empty($view->display[$view->current_display]->handler->handlers['filter'][$filter->options['id']]->value['min']) || !empty($view->display[$view->current_display]->handler->handlers['filter'][$filter->options['id']]->value['max'])) 

Hope it helps.

darrenphillips’s picture

Thank you. This is just what I needed.

tylerfrans’s picture

Thanks for posting this. It helped me out today!

yaworsk’s picture

Great post - thanks for posting it, definitely saved me some time!

ezekiel’s picture

I am getting a list of errors when trying to use this in my view along the HS module?

This is the error:

user warning: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') count_alias' at line 1 query: SELECT COUNT(*) FROM () count_alias in /sites/all/modules/hierarchical_select/modules/hs_taxonomy_views.module on line 535.

tribe_of_dan’s picture

I'm getting the same error except line 556. :/

ddbell’s picture

Great Solution:

One Problem:
The default "Any" selector does not work. If "Any" is selected by default and I click Apply, the results should show all results for that field. Currently nothing displays. I get "Sorry, no results were found. Please adjust your search criteria and try again.". If I select one of the drop down values and click Apply, this works fine by showing results that match the selection.

The solution works great except for this problem. Please help.

Did I miss something? Thanks.

salientknight’s picture

This worked thank you so much! One modification however, it was not running the PHP code from my Empty Text, even though it was set to PHP. It just showed the code -- come to think of it, I probably needed a <?php at the start ... anyway... this worked with normal text. A standard No Search Results ... message.

Thanks again...

tribe_of_dan’s picture

Oh I see what you're saying... same here. I wonder why?

Kars-T’s picture

get_exposed_input() might be nicer to use as this gives us all exposed filters. And you can immideately can set an empty text.

// This function gets us all exposed filters.

// You could debug this by using the devel module and dpm()
// dpm($view->get_exposed_input());
foreach ($view->get_exposed_input() as $filter => $value) {

  switch($filter) {
    // Date fields with multiple selectboxes as filters. The filter name is
    // set in the views configuration.
    case 'date_filter':
    case 'date_filter_1':
      // Change this as it fits for you. The date field behaves a bit
      // strange if not all values are set. So maybe && would be an better
      // option.
      if(
        $value['min']['day']
        || $value['min']['month']
        || $value['min']['year']
        || $value['max']['day']
        || $value['max']['month']
        || $value['max']['year']
        ) {
        return TRUE;
      }
      break;
    // Anything is check if its not all or empty. We still might get problems
    // if we get more complicated fields and setup a special case.
    default:
      if ($value !== '' && $value != 'All') {
        return TRUE;
      }
      break;
  }
}
// Set an empty text for the current display.
$view->display[$view->current_display]->handler->set_option('empty', 'Our "no filter is set" text.');
return FALSE;

--
Best regards

Karsten Frohwein

ddbell’s picture

Where should I place this code exactly. Please explain step by step. New to drupal. Thanks.

amal850720’s picture

subscribe

vicky_talkin’s picture

sorry to post here this but i didnt found the help any where and i think this is a little related to my following problem.
in my project i have 3 cck fields for Country,state ,and city
city is controlled by state and state is controlled by country..
i use these fields 2 times first for from address and second for to address.
now i use them in views as exposed filter for searching but there these fields are not dependent and showing the whole data .so i want to make them dependent in views filter so that when user change the value of country state list should be updated and the cities list too also is there any method or any patch to do this .
plz help this is the last point which i have to complete and getting no idea about it :(
if i can do this by custom coding to make these fields dependent plz suggest how.

drwierdo’s picture

I am having similar problem...i too want to conditionally expose some fields in the views filter...so did you find any solution??

yaworsk’s picture

you can use hook_views_pre_render to conditionally changed the exposed filter form - http://api.lullabot.com/hook_views_pre_render

pete

grasmash’s picture

Check out the Views Hacks module. Specifically, the Views Selective Exposed Filters submodule. It apparently "Restricts exposed filter values to those present in the result set." Sounds like what you're looking for.

anrikun’s picture

Very useful post!

Now the last step for filters of type Select would be to turn the default value "Any" to something that applies more in this case, like "Please select".

Amir Simantov’s picture

Hi, this is my code for dealing with this issue. I call this function in my template for a specific view in order to render $rows and $pager only if this functions returns true.

Note 1: that I use this view (the term page override one which comes with Views) both for a specific term and for a general search page of the site (using 'all' as argument). This is why I have added the first condition - I need this trick only for the second use. It may not be needed in your case.

Note 2: Not all types of filters are checked. Works for text fields, number fields and select list fields.

function is_filtered($view){

  if(!(current_path() == 'taxonomy/term/all')){
    return true;
  }

  foreach ($view->filter as $filter) {
    if ($filter->options['exposed']) {
      $value = $view->display[$view->current_display]->handler->handlers['filter'][$filter->options['id']]->value;

      // This is not a simple text field
      if(is_array($value)){

        // This is a select field and a value is selected
        if(isset($value[0])){
          return true;        
        }
        // This is a number field with a text inside
        elseif(isset($value['value']) && !empty($value['value'])){
          return true;        
        }
      }
      // This is a non-array field, i.e., a regular text field
      elseif (!empty($value)) {
        return true;
      }
    }
  }
  return false;
}