So I have a Drupal 8.5.5 with a View with a single Block display. This block has an exposed input set. I recently learned that the exposed form will not appear unless you configure the Block to use AJAX, which doesn't suit my purposes. Therefore I'd like a way to set the Exposed Input manually via a hook (or some other means).

I have tried populating the exposed input via several hooks, but none of them are influencing the results of the block, they just appear to be ignoring it. Enabling AJAX on the Block does work, but like I say this does not suit my purposes.

So I've tried:

function my_module_views_pre_build(\Drupal\views\ViewExecutable $view) {
  if ($view->id() == 'my_module_view' && $view->current_display == 'block_1') {
    $view->setExposedInput(array(
      'keywords' => 'Hello, World',
    ));
  }
}

But it's not picking it up. I've also tried `hook_views_pre_execute` with the same code but it doesn't work either.

Has any one managed to do this before?

Comments

julbo’s picture

Hi Alex,

I had the same functionnality on my website, and the setExposedInput function didn't work.

Instead, I had to use the exposed_raw_input attribute.

This is my code :

$view->exposed_raw_input = array_merge($exposed_filters, (array)$view->exposed_raw_input);

I put my custom exposed filters in an array like this :

$exposed_filters = ['name_attribute' => 'value_attribute'];

I hope that can help you. I can't help you with which hook to use because I previously loaded the view with views_get_view function, so the hook doesn't really matter in my case.

Regards, 

Julbo.

JBHUTT09’s picture

I don't know if you're still looking for an answer, but:

  1. Setting the exposed input in hook_views_pre_view() should work.
  2. If the filter whose input you're attempting to set is exposed, make sure you're using the exposed identifier when setting the exposed input, rather than the filter id.
cmoeser’s picture

Previously this worked, but stopped at some point:
$view->setExposedInput(['field_attached_listings_target_id' => $nid]);

Now I changed to to julbo's solution and is working again. Thanks julbo!

chandu7929’s picture

 I tried it setting in hook_views_pre_view(ViewExecutable $view) and its working fine.

$exposed_filters = ['title' => 'Example'];
$view->setExposedInput($exposed_filters);
lawsands’s picture

Has Anyone tried setting multiple exposed inputs and succeded?

jmmartos’s picture

Did you find any solution for multiple exposed inputs?

Thanks!

cmoeser’s picture

This has worked for me

$my_view->setArguments(array(implode('+', $myCatTIDs))); 

tanvirahmad’s picture

It shows, TypeError: Argument 1 passed to HOOK_views_pre_view() must be an instance of ViewExecutable

t@n

kevinfunk’s picture

Add the use statement Drupal\views\ViewExecutable or 

hook_views_pre_view(\Drupal\views\ViewExecutable $view, $display_id, array &$args) {
}

see hook_views_pre_view

FlxAlbroscheit’s picture

In addition to julbo's comment: Kindly note that ViewExecutable::setExposedInput overrides any previously existing filters. If you wish to add filters (or sorting) to an existing filter-query, better go with:

$view->setExposedInput(
array_merge(
   $view->getExposedInput(),
   $may_custom_filters_array
)
);
camerongreen’s picture

For a more complete example, this utilises a different hook but should do the same thing.  This demo works on the default content view, lower casing whatever you put in the title.

Note, as you will see, the reversed string is viewable by the user.  If you want to hide the parameter manipulation, you will need to use the query alter hook etc. (btw flush the case when you change this)

use Drupal\views\ViewExecutable;

/**
 * Implements hook_views_pre_view().
 */
function mymodule_views_pre_view(ViewExecutable $view, string $display_id, array $args) {
  if (($view->id() === 'content') && ($display_id === 'page_1')) {
    $exposed_input = $view->getExposedInput();
    $exposed_input['title'] = strtolower($exposed_input['title']);
    $view->setExposedInput($exposed_input);
  }
}
peter pulsifer’s picture

I have exposed filters displayed in a block form, and am using AJAX. I can change the filter values using hook_views_pre_build() or hook_views_pre_view() and $view->setExposedInput($newfilters) but I cannot change the filter values displayed by the exposed filter block. Apparently the displayed values are taken from the defaults and are not the actual filter values used for the query.

This might be a different situation from exposed filters that are set up programmatically.

With hook_views_pre_view(), I find $view->filter is an empty array; with hook_views_pre_build(), $view->filter is set to the filter values.

Using $view->setArguments() sets the contextual arguments for the view, not the exposed filter values.

I have tried using a form hook to change the displayed filter values, but that also has no effect. With the form hooks you can change the way the values are displayed (or hide the filter entirely) but you don't seem to be able to alter the displayed values.

I'm investigating whether I can fake a query string to change the exposed filter form; or I might have to resort to changing the values with JS. It's good to be able to customize the filters, but it's bad to have the results not match the filter display.