Yes, i know...this is another issue about how to alter an exposed filter form and i've read a lot about it but that's my situation.
I have to provide the administrators of a website the ability to change the default value in an exposed filter so to show the content they like by default changing it by a simple setting in an administration page.

That's the case, i thought i could simply change the default value in the form and everything would have worked the way i wanted but after enabling the module i've created to do this the value in the form conseguently changed while the view remained exactly the same.
Not even the value in the select changed, while inspecting the form the #default_value is the right one, so i'm able to handle the form values but not to make them really change the views item being shown or the "selected" value inside the select form.

What to say about the view...it is a particular display of a view, it uses ajax, the form is autosubmitted using jquery and the exposed filter got a default value in the views ui.

I don't want to put code in this issue for now since everything is working about altering the form but i can't see any change in the view being rendered.

What am i doing wrong?
Thanks,
Da.

Comments

merlinofchaos’s picture

Status: Active » Fixed

The trouble is that $_GET forms are tricky, and #default_value doesn't actually always work.

So Views will actually put the default data in $form_state['input'][$identifier] which is a copy of $_GET normally. In order to modify this default value, you're going to have to modify that. BUT you're going to have to be careful not to overwrite any data that was actually sent, so you will need to see if either $_GET[$identifier'] is unset (at which point, modify the $form_state['input']) -- if you might be getting the input from another source than $_GET you can also check out...I think it's $view->exposed_input. I forget exactly but a dsm() should find it quickly.

planctus’s picture

Thank you so much merlin, everything is working now...
I'm impressed how you were able in such a short explanation to make everything clear to me...
I've just spent a little amount of time trying to find out which was my "source", if it was $_GET or anything else...at last it was the first one even if this is not something i could completely understand...

This opens an entire world of possibilities and i think it would be interesting to make this a plugin for views in order to give an "administrator" the ability to change the setting about a default value of an exposed filter without giving him the hard task to administer views, for example.

Thank you, again :-)
Da.

Status: Fixed » Closed (fixed)

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

mrbangkok25’s picture

Status: Closed (fixed) » Active

Hi,

I am trying to accomplish something similar.
I am trying to to set the default_value of a select list, with hook_form_alter.

I can see the value comes from $form_state['input'][$identifier], i am able to change that, but as mentioned in post #1 i apperantly overwrite the data being sent. Because whatever i chose in my select list, it always show the result of the default_value, and changes the selection of the select list back to it's default_value.

I also took al look at $view->exposed_input, but that is not set.

Am i missing something ? what am i doing wrong ?

Thanks,

dagmar’s picture

Status: Active » Postponed (maintainer needs more info)

Please provide the code that you used.

myvo’s picture

I have the same problem. Here's what I've been trying:
- My views type: block
- Use Ajax: YES
- Views version: I try to use other version 6.x-2.11

function mymodule_form_alter(&$form, $form_state, $form_id) {
    //the field type is select.
    $nodeid_filter = 'node_nid';

    //$_GET[$nodeid_filter] = 5
    $nodeid = $_GET[$nodeid_filter];
    if ('views_exposed_form' == $form_id) {
        foreach ($form_state['view']->filter as $field => $filter) {
            if ($filter->options['exposed'] && $filter->options['id'] == $nodeid_filter) {
                $nodeids = array(
                    2    => 'Title 1',
                    5    => 'Title 2',
                    10   => 'Title 3'
                 );
                $form[$nodeid_filter]['#options'] = $nodeids;
                if(array_key_exists($nodeid, $nodeids)) {
                    $form[$nodeid_filter]['#default_value'] = $nodeid;
                }
            }
        }
    }
}
planctus’s picture

I'm sorry i didn't post my solution until now, i'll give an example of what i did, you'll see it is very simple:


function yourmodulename_form_alter(&$form, $form_state, $form_id) {
  if($form['#id'] == 'formId') {
    if (empty($_GET['exposed_filter_name']))  {
    $form_state['input']['exposed_filter_name'] = 'default_value';
    }
  }
}

Basically, you check that the form values are not already submitted and then put your desired value for a field.
In my situation i had a form to store that default value, letting the admins choose it so i could retrieve it using variable_get().
I hope this will help users to get through this.
Da.

esmerel’s picture

Status: Postponed (maintainer needs more info) » Active

Is this something that should get documented? Patched?

nicksanta’s picture

I had this problem too. @merlinofchaos's solution in #1 didn't solve the problem for me however, as I simply wanted a default value sitting in the form field without the default value passed into the query.

I came up with this solution which isn't particularly clean, but got the job done.

<?php

// We're using a constant because it is exceedingly difficult to have a default value in an exposed filter
// without actually passing that value into the query. We use this constant so that we have a reliable
// string to replace and remove from the query if we need to.
define('IAD_CUSTOM_BOOK_CLUB_SEARCH_DEFAULT_STRING', t('Club name...'));

/**
 * Implement hook_form_alter
 */
function iad_custom_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'views_exposed_form' && $form_state['view']->name == 'og') {
    if (!isset($_GET['title'])) {
      // @see constant definition for why we're using it here...
      // @see also hook_views_pre_execute
      $form['title']['#value'] = IAD_CUSTOM_BOOK_CLUB_SEARCH_DEFAULT_STRING; 
    }
  }
}

/**
 * Implement hook_views_pre_execute
 */
function iad_custom_views_pre_execute(&$view) {
  if ($view->name == 'og' && $view->current_display == 'page') {
    $query = &$view->build_info['query'];
    // @see constant definition for why we're using it here...
    // @see hook_form_alter
    $key = array_search(IAD_CUSTOM_BOOK_CLUB_SEARCH_DEFAULT_STRING, $view->build_info['query_args']);
    if ($key || $key === 0) {
      $search = " AND (UPPER(node.title) LIKE UPPER('%%%s%%'))";
      $query = str_ireplace($search, '', $query);
      unset($view->build_info['query_args'][$key]);
    }
  }
}
?>
iamjon’s picture

Status: Active » Closed (fixed)

Closing from lack of activity. Please feel free to reopen.

WildKitten’s picture

Just to give some explanation.

in #7 :

  • change 'formId' with the name of your view id, which you can get with print $form['#id']; in same function
  • change 'exposed_filter_name' with the name that you entered in the input field 'Filter identifier' for your exposed filter
  • change 'default_value' with your default value

in #9

  • 'views_exposed_form' stays the same
  • change 'og' with the name of your view
  • change 'title' with the name that you entered in the input field 'Filter identifier' for your exposed filter
  • change 'page' with the current display of your view, which you can get with print $form_state['view']->current_display; in yourmodule_hook_alter() function.
  • change 'UPPER(node.title) LIKE UPPER('%%%s%%')' (maybe you'll just have to change 'node.title' if you are using operator 'Contains' for your filter). You'll find your corresponding condition when you edit your view and see it's query written under view edit form.
Amir Simantov’s picture

Thanks for this thread, I think I am in the right direction. However,I have trired #7 and I might need some help.

Here is my code:

<?php
function viewscustom_form_alter(&$form, $form_state, $form_id) {
  if($form['#id'] == 'views-exposed-form-media-buzz-filtered-page-1') {
	//print $_GET['year']; Gives error of undefined index
    if (empty($_GET['year']))  {
    $form_state['input']['year'] = '2012';
    }
  }
}

The Filter identifier (under 'More' fieldset) in my case is 'year' and is what I understand to be the 'exposed_filter_name', or isn't it? However, trying to print $_GET['year'] gives me an error of undefined index.

What do I do wrong?

Thanks!

planctus’s picture

You might simply try to check if the filter was already used doing this:
if(!isset($_GET['year']))
See you,
Da.

Amir Simantov’s picture

@planctus
This does not help me because I need to make filtering, not to check whether filtering was made...

JSCSJSCS’s picture

#7 does not work for me either. I think it is because I am exposing the location distance/proximity field which really exposes three filters (postal code, distance, units of distance) under one filter identifier (distance). Just checking if it is blank doe snot work because the miles has a default value (10) and so does the units (miles). Leaving the zip code blank still gives a distance output, but one with no zip code.

I do;t know how to modify #7 for my use case.

My URL string after input:

http://example.com/locator/proximity?distance%5Bpostal_code%5D=92112&distance%5Bsearch_distance%5D=10&distance%5Bsearch_units%5D=mile

It really gets messy when there is a pager!

Since I am showing a gmap of locations, I want to stop someone from entering and empty zip code exposed filter, as that map takes forever to load.

Frippuz’s picture

A comment on this.
I tried to add a "Please choose" alternative to a views exposed filter. Among other things I hade problems adding my new option to the top. I also had problems setting the default option. In the end I ended up with the following:

function my_module_form_alter(&$form, $form_state, $form_id) {
   if ($form['#id'] == 'views-exposed-form-accessories-page-1') {
      $form['#after_build'] = array('my_module_types_after_build'); 
   }
}

function my_module_types_after_build($form, &$form_state) {
    $form['type']['#options'] = array_reverse($form['type']['#options'], true); 
    $form['type']['#options']['choose'] = 'Please choose';
    $form['type']['#options'] = array_reverse($form['type']['#options'], true);
    //$form['type']['#default_value'] = array('choose' => 'Please choose');
    if(!isset($_GET['type']))
      $form['type']['#value'] = 'choose';

    return $form;
}

It's strange that I need to set "#value" instead of "#default_value".

milehighlife’s picture

JSCSJSCS,

I'm curious if you were able to solve your issue with the 'blank zip code field' and what you did? I have a related problem: if a zip code is not given, I'm wanting to unset the distance field.

Thanks!

purabdk’s picture

Form alter will does not override the default value of an exposed filter.

you need to use the view hooks for that. I used following code in my module. which is working fine.

/**
 * hook_views_pre_view
 * @param type $view
 * @param type $display_id
 * @param type $args
 */
function MODULE_NAME_views_pre_view(&$view, &$display_id, &$args) {
  if ($view->name == 'VIEW_NAME') {
    $filters = $view->display_handler->get_option('filters');    
    $view->display_handler->override_option('filters', $filters);
  }
}



/**
 * hook__views_pre_build
 * @param type $view
 * @return type
 */
function MODULE_NAME_views_pre_build($view) { 
  if ($view->name=='VIEW_NAME') {    
    $view->display['page']->handler->handlers['filter']['filter_field']->value['value'] = 8;
    return $view;
  }     
}
merlinofchaos’s picture

form alter can override the default value of an exposed filter, but you need to check and potentially set $form_state['input'] instead. This is because GET forms are automatically considered to be submitted whether or not a button was pressed because there isn't a POST event to check.

xeeshangulzar’s picture

Issue summary: View changes

#7 works for me. Great Job!

helenc’s picture

#7 works for me also, with the exception of using !isset rather than empty, e.g.

if (!isset($_GET['exposed_filter_name']))  {
    $form_state['input']['exposed_filter_name'] = 'default';
}

The reason being that 'empty' will return true for a value of '0', and my select box has 0 for one of the values.

sylvaticus’s picture

I can't get #7 to work, maybe because in my case the exposed field is a node reference field.

function MYMODULE_form_alter(&$form, $form_state, $form_id) {
  if($form['#id'] == 'views-exposed-form-rivista-page' && $form_id ="views_exposed_form") {
    if (!isset($_GET['MYEXPOSEDFIELDID']))  {
      dpm("Test passed");
      $form_state['input']['MYEXPOSEDFIELDID'] = 'MYWANTEDNID';
      $form_state['view']->exposed_input['MYEXPOSEDFIELDID'] = 'MYWANTEDNID';
   }
  }

Using dpm($form) and dpm($form_state) I can see that the values are actually changing, and so they do if I manually select the desidered option, but I can't set the default option on the desired value.
Any hint ?

dagomar’s picture

@sylvaticus

I had the same problem, however I think it was due to some browser caching, so I suggest to try the result in an incognito window. Then it worked for me!

mudjunky’s picture

I could not get #7 to work in 6.x-3.2. I used this instead:

function mymodule_views_pre_view(&$view, &$display_id, &$args) {
  if ($view->name == 'my_view_name' && $view->current_display == 'my_view_display') {
    if (empty($_GET['exposed_filter_name'])) {
      $view->set_exposed_input(array('exposed_filter_name' => 'default_value'));
    }
  }
}
niccottrell’s picture

In Drupal 8.x something like this should work:

function MYMODULE_form_alter(&$form, $form_state, $form_id) {
  if($form['#id'] == 'views-exposed-form-rivista-page' && $form_id ="views_exposed_form") {
    $request = \Drupal::request();
      if (!$request->get('MYEXPOSEDFIELDID', NULL)) {         // no param set
        // reference to user input object (for editing)
        $input = &$form_state->getUserInput();
        $input['MYEXPOSEDFIELDID'] = NEWVALUE;
      }
    }
jbd44’s picture

To set a default value:

function my_module_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if ($form['#id'] == 'views-exposed-form-my-view-display') {
    $request = \Drupal::request();
    if (is_null($request->get('foo'))) {
      $form_state->setUserInput(['foo' => 'bar']);
    }
  }
}