Problem/Motivation
If a view has a page and (for example) block display, the page display's path is always used as the #action for the block's exposed form. This means when the block is placed on another page, and the exposed form is submitted, the user is redirected to the page display's path.
Steps to reproduce
1. Install standard
2. Edit the Content view and add a Block display, disable AJAX on it and save
3. Add the Block to the Content region
4. Go to the frontpage and submit the exposed form
5. You will be on admin/content
This is going wrong in: \Drupal\views\Form\ViewsForm::buildForm() in line 160
$form['#action'] = $view->hasUrl() ? $view->getUrl()->setOptions($options)->toString() : Url::fromRoute('<current>')->setOptions($options)->toString();
- hasUrl calls getRoutedDisplay on the current display handler
- getRoutedDisplay calls getLinkDisplay
- By default (in DisplayPluginBase) getLinkDisplay checks the link_display option, and if it's empty, iterates through each display looking for a path. Once it finds one it returns that display. This is where it finds the page display and how the action ends up as admin/content in the steps above.
#2844823: Views exposed form action incorrect for embedded views' displays with other displays with paths has been marked as possible duplicate and may also contain additional relevant information
Proposed resolution
Don't iterate through display handlers in Block and Embed plugins for getLinkDisplay.
Remaining tasks
Tests
Resolve BC issues in #75
Review
Commit
| Comment | File | Size | Author |
|---|
Issue fork drupal-2840283
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
jurgenhaasI looked again and it could also be that this is a core issue. There is a patch that resolves the issue and views is doing similar things with overrider path elsewhere, e.g. for more-links. So probably its just been forgotten for form action paths?
Comment #3
jurgenhaasComment #4
ahebrank commentedI can see how this might confuse the routing system. This is a form within a view within an entity, right?
The simply workaround that comes to mind would be to add an eva display option to force the view override_path to the current URL (meaning add a conditional here: https://github.com/ahebrank/eva/blob/8.x-1.x/src/Plugin/views/display/Ev...). I'm assuming this block isn't executing in your case because the page display has set override_path already?
Comment #5
jurgenhaasThe override path is set to exactly what would be the correct value, it's just that views doesn't utilize that override path and does its regular thing. The patch is fixing that in views, not in EVA.
Comment #6
ahebrank commentedOK, thanks for clarifying. Sounds like this is best left as an upstream issue.
Comment #7
jurgenhaasReassigning this issue to Drupal core as it seems to be an issue there.
Comment #8
lendudeThis fix makes sense to me, setting to needs review to trigger the testbot, but this needs test, so needs to go to needs work.
Comment #10
jurgenhaasFix patch format (shame on PhpStorm, always requires manual intervention). Sorry for that.
Comment #12
jurgenhaasOf course it also needs the leading core directory.
Comment #13
lendudeWe got a passing fix, nice!
Setting back to needs work for tests.
Comment #14
jurgenhaasThanks @Lendude, may I ask for some advise here? I haven't ever written a test for core yet and with views, it seems particularly hard as we have to produce a couple of views with extra forms being displayed on different pages to see if we get different action paths. Can you point me in the right direction here?
Comment #15
lendude@jurgenhaas I agree a full integration test for the scenario you describe would be a little elaborate. So keep it simple and focus on the change being introduced in core. I would look into a kernel test that just loads the View, sets
$view->override_pathand then renders the View. Then check if the rendered HTML contains the correct action.That should cover the change being introduced here. If you want to do a full integration test for the scenario you describe, that might be better to put into EVA, since there such a scenario might be much more relevant.
I did a quick look but couldn't find a test for
\Drupal\views\Form\ViewsFormyou can use as a starting point for this unfortunately.Comment #16
jurgenhaasFor the last couple of days I investigated a bit more and ended up in \Drupal\Tests\views\Kernel\Plugin\ViewsBlockTest and thought I could extend my test in there.
Problem being: when I want to set the override_path I do require a form in the view in the first place. Now, embedding a form into a view should be working through exposed filters. So I've created a view with a page and a block display and also added an exposed filter.
Next I realised that this exposed filter does show on the page but not inside the block. Investigating further brings to lite that exposed filters in blocks are only displayed when ajax gets enabled. When doing that, I'm getting the form in the block that contains the view and I could now develop the test on top of that.
The views that are tested in blocks so far are defined in core/modules/block/tests/modules/block_test_views/test_views and I will add a new view in there just for this test. I hope this is the correct approach.
Comment #17
jurgenhaasFeels like I've chosen a fairly tricky area for my first core test here ;-) Well, maybe. Let's give it a try.
Comment #19
jurgenhaasRegister the new view for tests in the block module.
Comment #21
lendudeBit of a nudge, config errors can be tricky to figure out.
This test covers the change to
\Drupal\views\Form\ViewsExposedForm, so we still need one for the change to\Drupal\views\Form\ViewsFormright?Also, it's a good idea to add an interdiff when you post a patch, makes reviewing much easier. Look here for a how-to.
Comment #22
jurgenhaasGreat, the test passed successfully, thanks a lot @Lendude
Yes, that test covers
\Drupal\views\Form\ViewsExposedFormand I wonder what other forms a view can have. Am I missing the forest for all the trees?Comment #23
lendude\Drupal\views\Form\ViewsFormis used whenever a View field contains a form element (a handler that implements viewsForm).Maybe take a look at what
\Drupal\views\Tests\ViewsFormMultipleTestis doing. And look at\Drupal\views_test_data\Plugin\views\field\FieldFormButtonTestfor an example of a handler implementing this.Shameless plug: check the PR in #2834812: Add a views handler for a per-variation add to cart button for a real life example of its use.
Comment #25
jurgenhaasRe-roll the patch required by DRD to work with shortened array notation.
Comment #26
vinay15Comment #27
millionleaves commentedPatch in #25 assumes views is in modules/views rather than core/modules/views. Modifying the paths in the patch fixed the problem for me.
Comment #28
jurgenhaas@millionleaves AFAIK patch files are defined from the root of the affected project, in this case Drupal. And the patch should not make any assumptions with regards to where that project is being installed. Instead, the patch process itself should be aware of where it is located and call the patch process from that location. E.g. if you deploy with drush make or with composer, they both work just fine with the patch as is.
Comment #29
shawn_smiley commentedAnother scenario that seems to exhibit this issue is with attached displays to block displays.
For example, I have a block view display that renders a list of content related to the currently displayed page. This block includes bulk operations for the related content. It also includes a display attachment via the views_data_export module for exporting a CSV of the related content.
I'm still tracing through the code to understand what is happening, but it does appear that in this case there was an intentional decision in DisplayPluginBase.php to set the form action to the URL of an attached view when the display is a block.
Related ticket in the views_data_export module issue queue: https://www.drupal.org/node/2881076
Comment #33
balbuf commentedIn my case, I had a view whose main display is a block (with an exposed form), then I added a second display that is a REST Export. The block doesn't have its own route, so when it was just the block in that view, it correctly used the current route for the action of the form. Once I added the REST Export display, which does have its own route, the block started using that route instead of the current route where the block was placed.
This is a result of the technique used to find a valid route: the
getLinkDisplay()method is used to find a display within the view that actually does have its own route. The Block display plugin does not override the default logic of this method, which simply returns the first display that has a route. When the block was the only display in the view, this would return NULL and the form action would default to the current route. Once I added another display which had a route, that display was being returned and used for the form action.I believe this behavior is incorrect, because the Block display plugin exposes an option to choose a linked display, and by default, the value is "None":


Therefore, defaulting to any other random display that the view contains to use as the linked display when determining the action value for the block's exposed form is a bug IMO. The attached patch makes sure the user-selected linked display is used by a block, which may be "None." The "Custom URL" option is not handled, as I don't personally have a need and it seemed more involved, but I would expect that option to be honored by the block display plugin as well.
Comment #34
johnpitcairn commentedComment #35
johnpitcairn commentedThis problem occurs for exposed forms in entity attachments too. Don't think the patch applies to dev any more, let's see...
Comment #36
johnpitcairn commentedSame patch as #33 ... go testbot ...
Comment #39
tbenice commentedThe embed display type has the same problem. I cant add a patch right now.
Comment #40
tbenice commentedHere is a new patch for both block and embed displays.
Comment #41
tbenice commentedre-roll wrong path in the last patch.
Comment #42
tbenice commentedone last time
Comment #43
meenakshig commentedComment #48
carsoncho commentedRe-roll of #42 for 9.1.x
Comment #49
carsoncho commentedChoose wrong core version to test with.
Comment #50
vsujeetkumar commented@carsoncho Patch #42 applied successfully on 9.1.x, So there is no re-roll required, also the re-roll you provided in #48 is incorrect according to the #42, For the reference I have added test on #42, Please have a look.
Also there is custom command failed issue because comment added after statement.
Comment #54
nikhil_110 commentedTry to fixed Cc Issue #48, #49 && Attached patch against Drupal 10.1.x
Comment #55
nikhil_110 commentedCc Issue Fixed #54
Comment #56
akram khanadded updated patch try to fix CCF #54
Comment #59
jonraedeke commented#42 Works well for D9. Thanks!
Comment #60
bohus ulrychFYI patch #42 still works, tested on Drupal 10.1.6
Patches posted later doesn't work - tested with View with exposed filters using views_embed_view(), where is attached Data export display (module views_data_export, reported in issue 3166881 of this module).
Comment #61
maskedjellybeanWith patch #56 applied to Drupal 10.1.6 I get this error in watchdog when submitting (pressing submit/apply button) with an embedded view with AJAX enabled and with exposed filters:And it seems that the exposed filters have no affect on the results.EDIT: This was not caused by the patch. It was caused by restricting access to the view by permission. An unrelated issue apparently.
Additionally when resetting the view using the reset button, despite having AJAX enabled for the view, the entire page is reloaded and I am taken to the top of the page. This is less than ideal.EDIT: This is the behavior of the reset button regardless of whether the patch is applied or not. Still not ideal.
Comment #62
toby-fz commentedI also had this issue and solved it with the patch from #42. I didn't try any of the other patches based on #60
I am on views_data_export 1.2 on drupal 9.5.11.
Comment #63
liam morlandPatch #42 is working for us on Drupal 10.1.
Comment #64
smustgrave commentedStill needs tests. Also issue summary should follow the standard issue template please.
Comment #65
solideogloria commentedHiding problematic patches, since #42 is still what people are using.
Comment #66
solideogloria commentedEverything should be converted to a merge request as well.
Comment #68
liam morlandOpened a merge request with the patch in #42.
Comment #69
solideogloria commentedComment #70
solideogloria commentedComment #71
solideogloria commentedComment #72
divya.lakshman commentedThe patch on #56( 2840283-56.patch) fails to apply on Drupal version 10.4.1
Comment #73
acbramley commentedComment #74
acbramley commentedComment #75
acbramley commentedAs part of fixing the test failures I realise this change is going to be a bit problematic for BC. I.e users may have blocks or embeds that they want to automatically link to the page display which would no longer be the case after this change, and at worst could throw a 500 with
You cannot create a URL to a display without routes.which was one of failures in ArugmentDefaultTestComment #76
jurgenhaasComment #77
acbramley commentedComment #80
arlina commentedThere is another scenario that needs to be considered: when setting the action path, if the view was refreshed via AJAX, then the path is set to
<current>, which translates to "view/ajax...". Submitting the form then fails.I've added a new MR (MR !13479) that extends the existing work, adding a new method to determine the action's URL taking AJAX into account.
Comment #81
anybody#2844823: Views exposed form action incorrect for embedded views' displays with other displays with paths has been marked as possible duplicate and may also contain additional relevant information
Comment #84
joelpittetI’ve hidden MR !8053 to avoid a bit of confusion and/but opened a new MR !14412, to preserve some of the work and testing I’d already done in #2844823: Views exposed form action incorrect for embedded views' displays with other displays with paths.
That testing was done manually on a real project (VBO + exposed filters on a block display with a data_export display), which helped validate a few edge cases.
I didn’t want to step on the work in MR !13479. The approach is very similar, so I’m comparing against it and folding in only what helps reduce the diff and close any remaining gaps.
Comment #85
acbramley commented@joelpittet thanks for the tidy up, does your MR address the issues raised in #75?
Comment #86
joelpittetMR !14412 is ready for review.
This builds on a lot of hard work that’s already gone into this issue across multiple MRs. My intent here is not to step on toes, but to try to move things a bit closer to a finish line on a long-running and understandably tricky issue. Aside from a small class property name change, I did not merge the other MRs directly, though they very much informed this approach.
I added a post_update hook to preserve BC while removing the guessing behaviour, to avoid unexpected side effects. This will affect my own project(s), but I believe the end result is more predictable behaviour overall.
If this isn’t the right direction, or if other MRs are closer to the mark, I’m completely fine with this one being closed. I’m not attached to it (EDIT: well a little bit attached 😉 but I can deal!). My hope is that, even if this MR isn’t taken, some of the ideas here are useful and help move the issue forward! ➡️
This likely needs a CR. I’m happy to draft one if this approach looks acceptable (though I don't want to create one if I am off base).
Comment #87
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #88
joelpittetThe review bot went after the other MR. I just fixed the PHPCS issue it reported to keep it from moving back to NW. Please review #86
Comment #89
acbramley commentedI think we just close the old MR at this point?
Comment #93
smustgrave commentedLeft a question on the MR but it also needs a rebase.
Also can probably start the CR.
Thanks!
Comment #94
joelpittetCR added https://www.drupal.org/node/3579301
The reroll was a bit tricky but I think I got it. Responded to MR comments.
Comment #95
d.fisher commentedMR!14412 is failing to apply for me now on Drupal core 11.3.5. Not sure if this is as a result of the rebase?
Comment #96
smustgrave commentedThanks @joelpittet responded to the comment with a small change request to use constructor promotion. Less lines.
Comment #97
liam morlandI have added constructor property promotion for the new property.
Comment #98
joelpittet@d.fisher re #95 that is very unlucky but also very possible – we are applying it against the main branch which might have changes that don’t gel well with Drupal 11.3.5.
It seems like we are on the homestretch for this issue (knock on wood) but you can create a patch out of the older commits with git diff.
(Hot tip, exclude tests from the diff/patch will yield less conflicts)
Comment #99
d.fisher commentedYes I suspect it will be some difference that has crept in between the tagged release and the main branch which is unfortunate but always something that can happen. I was just testing using the MR and adding .patch to the end. As it happens we've just switched to AJAX so this is no longer an immediate issue on the site I was testing it on but good to know this one is moving along! Thank you for all the hard work going on in here!