In lieu of there not yet being a D8 version of Views Selective Filters I'm trying to alter the options of an exposed filter of an EVA view (attached to taxonomy terms) using hook_form_views_exposed_form_alter to remove any terms that don't have the view's argument tid as a parent.
I've been doing something a bit like this:
function mymodule_form_views_exposed_form_alter(&$form, FormStateInterface $form_state, $form_id) {
$view = $form_state->get('view');
if ($view->id() == 'my_view_id') {
$arg = $view->args[0]; // get first argument from view
$vid = 'my_taxonomy';
$terms =\Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree($vid); // build term tree
$options['All'] = 'All'; // add wildcard option
foreach ($terms as $term) {
if(in_array($arg, $term->parents)){ // check if argument is parent of term
$options[$term->tid] = $term->name;
}
}
$form['category']['#options'] = $options;
}
}
However I only end up with the single hardcoded 'All' option. Deleting $arg and directly using a correct tid value does filter the options as expected.
If I do a ksm($view->args) using Devel inside the hook it seems to be called twice - once with the argument correctly filled, and then again with a NULL result. If I add additional logic to the hook to only operate on the form with populated arguments the exposed filter isn't altered at all.
Is there some reason arguments might not be passed correctly through the hook by EVA? When I add a Block or Page display to the same view (or alternatively use Viewfield to try accomplish the same thing as EVA) the hook works correctly (and is only called once).
| Comment | File | Size | Author |
|---|---|---|---|
| #13 | eva-2959751-13.patch | 1.71 KB | ahebrank |
| #5 | eva-exposed-form-arguments-2959751.patch | 1.42 KB | khalor |
Comments
Comment #2
ahebrank commentedDo you have the EVA argument handling set to 'None' ("No special handing", not the default 'id' or 'token')? 'None' should leave the $args alone but the other two will overwrite them (e.g., https://github.com/ahebrank/eva/blob/8.x-1.x/eva.module#L138)
I'm guessing the hook running twice has to do with the extra initialization that checks whether the exposed form exists (so that it may be represented as an additional extra field). If that's true, and that check can be done more cleanly, it'd be great to not process the exposed form twice.
Comment #3
khalor commentedIf I use 'None' for EVA argument handling and try populating it another way ('Provide default value: Taxonomy term ID from URL') the main body of the view receives the argument correctly (as it does when using EVA's 'id' option) but the double-firing of the hook now gets 2 NULLs for $arg instead of 1x NULL and 1x correct arg value.
After some digging it seems the exposed form isn't passed any arguments because we actually build it as a field before any of EVA's argument logic is performed (the exposed form is built on line 112 of eva.module, the arguments aren't set until line 123).
The double hook happens because we're actually building the exposed form twice: once as it's own field, then again as part of the view as it normally would be - it's just not displayed due to {{ exposed }} being removed from eva-display-entity-view.html.twig.
An easy fix for the arguments would be moving the exposed form field build until after all the other EVA argument logic has happened (a quick cut/paste didn't break anything immediately for me but there may be other issues I'm not aware of) - as for the double-hook firing perhaps we should be unsetting the exposed form from the view after the field is built instead of simply hiding it with the twig template?
Comment #4
ahebrank commentedThe first change (building the exposed form later) makes sense to me -- can you post a patch or PR on github?
For the second (unsetting the form before the regular render) -- maybe some trickery in overloading usesExposed() in the display handler so that View::build ignores the form? Something along the lines of:
and then call the first function in the EVA enumerator: https://github.com/ahebrank/eva/blob/8.x-2.x/eva.module#L82
Comment #5
khalor commentedHere's a patch changing the order of where the exposed form is built - I'll have a go at your suggestion for changing usesExposed() and see where we end up!
Comment #6
sinn commentedWe have the same issue with Views Selective Filters.
I couldn't applied patch #5 on latest dev version, so new version is attached. Also variable for exposed form were added to template eva-display-entity-view.html.twig. It was added because we are stuck with it. It wasn't obvious why exposed filter is shown on front end and isn't shown in back end.
Comment #7
ahebrank commentedI don't think we want the exposed filter displayed with the main View (template) since it's handled in a separate pseudofield. At least let's hold off on that idea until the rest of the patch appears to turn off the regular exposed form render.
Comment #8
khalor commentedIf we do
in the display handler and call usesExposedField() in eva.module the we correctly fire the hook once, and if you have AJAX turned off the page will refresh and filter the view correctly. However with AJAX turned on the view will refresh but not perform any filtering.
Comment #9
ahebrank commentedIf I've got the logic right, calling the form render function with $block = TRUE (as on https://github.com/ahebrank/eva/blob/8.x-2.x/eva.module#L115 already) should render the form while the default call from the view build would not... but only if some special block sauce is also set.
So maybe the next thing to try would be to define the exposed_block display handler option to TRUE and leave it hidden from the config UI. I don't know whether there are side-effects associated with that option.
Comment #10
sinn commentedWith patches 5 or 6 exposed form works with ajax enabled and without.
About #7: we are using {{ exposed }} to test EVA view display in back office. Otherwise testing of exposed filter is difficult.
Comment #11
ahebrank commentedAh, OK, the template for preview. Hmm. I was thinking we'd aim to be consistent with how exposed filters for Block handlers work, so that would mean no preview if I'm remembering correctly.
I guess the question of whether or not to a) prevent the double form render (like the block plugin) or b) whether to continue the double-render and fix the preview could move to a separate issue and we could go ahead and merge the first part (rendering the separate exposed form field a little later).
If one of you can do #6 against 8.x-2.x (without the template change for now) I'll go ahead and merge it. I'll follow up here with a link to the new issue for the second part.
Comment #12
khalor commentedI've just done a PR for moving the exposed form build against 8.x-2.x on github.
Comment #13
ahebrank commentedThanks, patch from PR in #12 attached. I'll go ahead and merge this.
Comment #14
ahebrank commentedComment #15
ahebrank commentedThis is linked in the sidebar, but let's figure out what to do with the rerender and preview here: https://www.drupal.org/project/eva/issues/2960656
Comment #16
ahebrank commented