Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Steps to recreate:
- Create an AJAX enabled view with exposed filters (as drop down), enable the reset button
- Create a page and place the view as a block on the page.
- Load the view page - no reset button
- Click filter submit button
- Reset button appears
- Click Reset button
- The page is redirected to a system/404
Comment | File | Size | Author |
---|---|---|---|
#129 | 2820347-129.patch | 13.59 KB | acbramley |
#129 | interdiff-2820347-126-129.txt | 2.13 KB | acbramley |
Comments
Comment #2
sittard CreditAttribution: sittard commentedComment #3
godotislate CreditAttribution: godotislate commentedLooks like there are a couple of issues
1. AJAX behavior is explicitly not applied to reset buttons (/core/modules/views/js/ajax_view.js)
2. Views AJAX is changing the form action to "/views/ajax" somewhere.
My workaround was to implement a form alter and explicitly set the form action to the correct URL.
Comment #4
acbramley CreditAttribution: acbramley at Department of Justice & Community Safety, Victoria commentedEncountered this today as well, in 2 different ways:
Firstly I had a page display in the same view as the block and tried writing some behat tests (i,e no javascript).
When the test hit the Apply button it was being sent to the page display with filters applied rather than the page the block was on. To fix that I had to move the page display to a new view, no biggy.
Second issue I've now encountered is as described here, except I get redirected to /views/ajax.
Comment #5
acbramley CreditAttribution: acbramley at Department of Justice & Community Safety, Victoria commentedThe bug seems to be coming from this line in Drupal\views\Form\ViewsExposedForm
When the exposed form is submitted via ajax, it sets the action to views/ajax
Comment #6
acbramley CreditAttribution: acbramley at Department of Justice & Community Safety, Victoria commentedHere's a failing test to prove the problem.
Comment #8
aimevpI'm having this issue as well but noticed I had a second side-effect caused by the line of code mentioned in #5.
In my view I had several blocks with exposed filters that worked until I added page display's. From that moment the exposed filters on the blocks started using the path's of the first page display in the form action, instead of the "current page".
I don't really understand why the code in views gets to decide where to redirect the form action to. "If it doesn't find a display with a path, redirect to current page". It seems so random to me.
Wouldn't it be better SBX to add a setting "Form redirect path (for example)" within the exposed filters options of each view display (or somewhere else within the view display settings) with a default setting "Current" in which the sitebuilder can define a page display or a path if needed?
Comment #10
kovtunos CreditAttribution: kovtunos commentedQuick fix with the hook_form_alter implementation:
Comment #11
acbramley CreditAttribution: acbramley commentedRerolling on 8.3.x with updated submit filter text as the default has changed.
Comment #13
acbramley CreditAttribution: acbramley commentedFix using the request referer if the current page is identified as the views ajax route. I'm not entirely fond of this approach but with my limited views foo this is what I've come up with. The other option would be to make Reset use ajax as well but that would be a more involved change. Let's see if this breaks anything.
Comment #15
acbramley CreditAttribution: acbramley commentedMissed this change to the test.
Comment #16
anpolimusExpecting this issue at my project.
Patch at #15 fix this problem.
I have one problem - when I'm using ajax at the view, reset button click refreshes current page.
Is it normal in this case?
Comment #17
acbramley CreditAttribution: acbramley commented@anpolimus yeah, that is the normal functionality. One option for fixing this would be to change the reset button to use ajax as well, but I think that is going to be a far broader change (without looking into it), probably best for another issue.
Comment #18
anpolimusIn this case, this isssue is fixed.
Comment #19
LendudeBit of nitpicking:
UUID needs to be removed
Shouldn't we check then that $this->assertNotContains('Article A', $html);
Comment #20
acbramley CreditAttribution: acbramley commentedThanks @Lendude, fixed those up.
Comment #21
Lendude@acbramley++
RTBC++
Comment #23
LendudeNeeds reroll for #2776975: March 3, 2017: Convert core to array syntax coding standards for Drupal 8.3.x RC phase.
Using the convert trick in that issue won't work here because only the trailing ) of array() is in the patch.
Comment #24
tameeshb CreditAttribution: tameeshb at Google Summer of Code commentedPatch rerolled.
Comment #25
tameeshb CreditAttribution: tameeshb at Google Summer of Code commentedComment #26
LendudeThanks @tameeshb reroll looks good, back to RTBC
Comment #27
alexpottI'm not sure about this. I think this might under certain circumstances allow an open redirect. We shouldn't trust a referer.
Comment #28
acbramley CreditAttribution: acbramley commented@alexpott yeah I didn't like the referer solution either, but I'm not sure how else to solve it. I tried using the parent request object but that wasn't working either. Any guidance here would be great.
Comment #29
jibran@acbramley I think you should ping @tim.plunkett about it. He might be able to help you out here.
Comment #30
LendudeBorrowed the solution from @dawehner in #2866386: Assert the view path is set correctly after second ajax request.
Also, the use of assertWaitOnAjaxRequest() can lead to random fails, so taken that out, but we don't have wait methods for removed elements yet, so added that too.
Comment #31
jibranThanks, patch looks good to me.
It can be converted
!==
.Comment #32
Dinesh18 CreditAttribution: Dinesh18 as a volunteer commented@jibra, could you please review the below code so that I can create the patch as per comment #31
+ if ($current->getRouteName() !== 'views.ajax') {
Comment #33
LendudeThanks for the feedback @jibran, here we go.
Comment #34
jibranThanks! @Lendude
Comment #35
Dinesh18 CreditAttribution: Dinesh18 as a volunteer commentedPatch #33 looks good and implements #31.
Here is a screengrab. +1 to RTBC
Comment #37
acbramley CreditAttribution: acbramley commentedThanks @Lendude, much nicer solution!
Comment #38
acbramley CreditAttribution: acbramley commentedConfirmed test failure locally.
EDIT: It seems like getRouteName() is always returning "" now. Not sure when this changed as it was certainly working before.
Comment #39
acbramley CreditAttribution: acbramley commentedFixed #33 failure
Comment #40
acbramley CreditAttribution: acbramley commentedComment #42
jibranInterdiff, please.
This can be removed now.
Comment #43
acbramley CreditAttribution: acbramley commentedSorry, forgot to upload the interdiff! Url is still being used here:
EDIT: Ahh from the test...fixing now.
Comment #44
acbramley CreditAttribution: acbramley commentedComment #45
LendudeLast little nitpick:
$current can go inside the if now
Comment #46
Dinesh18 CreditAttribution: Dinesh18 as a volunteer commentedComment #47
Dinesh18 CreditAttribution: Dinesh18 as a volunteer commentedHere is an updated patch and interdiff.
Implements #45
Comment #48
jibranThe last patch is not correct at all. @Dinesh18 please read https://www.drupal.org/patch/apply and https://www.drupal.org/patch first before uploading the patch. Thanks!
Comment #49
Dinesh18 CreditAttribution: Dinesh18 as a volunteer commentedHere is an updated patch which implements #45.
Comment #50
Anonymous (not verified) CreditAttribution: Anonymous at Cheeky Monkey Media commentedI found an issue with the patch and getting the path form the currentPathStack. On two of my sites, it returned the path prefixed with two /, and resulted in trying to go to a site with my path as the host name.
I've updated the patch to set $form_action to '' (current path) to avoid issues in setting/getting urls.
I also updated the tests to repeat the original test - checking for the 3 nodes.
Comment #51
Anonymous (not verified) CreditAttribution: Anonymous at Cheeky Monkey Media commentedSame patch rolled against 8.4.x
Comment #53
Anonymous (not verified) CreditAttribution: Anonymous at Cheeky Monkey Media commentedFixed weird error in 8.3 patch
Comment #54
Dinesh18 CreditAttribution: Dinesh18 as a volunteer commentedCould you please provide interdiff as well
Comment #55
Lendude#50 indicates we are missing test coverage here since the test we have is fine with using currentPathStack.
@rsmylski any chance you can indicate what was different in your situation then in the existing test?
Comment #56
mcvjoyner CreditAttribution: mcvjoyner as a volunteer and at Cheeky Monkey Media commentedI have tested the patch, and it works well. Thanks @rsmylski!
Comment #57
Anonymous (not verified) CreditAttribution: Anonymous at Cheeky Monkey Media commentedHere's the interdiff.
As for the test change - I changed the final test to check for the first things checked for to start the test, rather than checking for not being a 404. Ultimately, the last check of the urls should confirm we were on the same page.
Comment #58
Lendude@rsmylski++
Tested that the changed test coverage indeed fails with the fix from before #50, so we have coverage for the problems described in #50, nice work.
Comment #59
catchIt's minor, but why change from the ternary to the if/else? The ternary seems more readable here and it'll be a shorter line too.
Also even with the if/else could it not set $form['#action'] directly instead of the temporary variable? But for me I'd stick with the ternary.
Do we really not have anything usable for this purpose already?
Comment #60
acbramley CreditAttribution: acbramley commented@catch you're right, the if/else made more sense when were doing more than just setting it to an empty string. I can't comment on point 2.
Comment #61
LendudeThese are the wait options we have:
waitForButton
waitForElement
waitForElementVisible
waitForField
waitForId
waitForLink
waitOnAutocomplete
So no we don't have anything to wait for stuff to disappear as far as I can tell.
But we do need to remove the assertWaitOnAjaxRequest call, which I apparently failed to do :(
Comment #62
acbramley CreditAttribution: acbramley commentedFixes #61
Comment #63
LendudeFeedback has been addressed, back to RTBC
Comment #65
acbramley CreditAttribution: acbramley commentedThat fail looks unrelated.
Comment #66
LendudeCodesniffer did find an unused Use though, so lets take that out.
drupal/core/modules/views/src/Form/ViewsExposedForm.php:9 use Drupal\Core\Url;
Comment #67
acbramley CreditAttribution: acbramley at PreviousNext for Transport for NSW commentedFixed #66
Comment #68
Lendude@acbramley thank you!
Comment #70
catchThis needs a change record for the new method on WebAssert, but otherwise looks good.
Comment #71
acbramley CreditAttribution: acbramley at PreviousNext for Transport for NSW commentedChange record drafted https://www.drupal.org/node/2906685
Comment #72
LendudeCR looks good, back to RTBC
Comment #74
acbramley CreditAttribution: acbramley at PreviousNext for Transport for NSW commentedSeems like a CI blip
Comment #75
acbramley CreditAttribution: acbramley at PreviousNext for Transport for NSW commentedRetest passed, back to RTBC
Comment #76
xjmI wanted to test that this didn't regress or change other behaviors of the block exposed form, for a page that was the frontpage, etc., but I'm having some issues reproducing the bug.
I tested this by making the frontpage AJAX and adding an exposed form in a block with a reset button in HEAD. For me, in HEAD the reset button disappears strangely. If I navigate to e.g.
node/1
and apply the filter, I get redirected to the node frontpage (with itsnode
path) and have the reset button, which works. But if I reset the filters and then submit the exposed form from the page of the view itself, the reset button does not show up and I have no way of resetting the view results. Strange... But I was not able to reproduce the 404 at all, in HEAD or with the patch.https://www.drupal.org/pift-ci-job/556226 does seem to show a failing result so I'll try testing a scenario closer to the test view.
Meanwhile, uploading a new test-only patch since the failing result was on an earlier version of the test and an earlier version of Drupal.
Comment #78
acbramley CreditAttribution: acbramley at PreviousNext for Transport for NSW commentedHi @xjm, sorry but I don't quite understand your comments in #76, are you able to post steps to reproduce your problems? The FAIL patch has correctly failed and the other has passed so is there anything more to do in this issue?
Thanks!
Comment #81
jibranThe test fails seems unrelated.
Comment #82
AnybodyI just tested the patch manually and can luckily confirm RTBC :) It works now!
We've tested it in a multilang environment with translated reset button.
RTBC++ and please commit to next release! Should we perhaps set a higher priority, because it breaks things?
Comment #83
xjm@acbramley, I didn't have "problems"; I was describing what steps I, as a Drupal core committer, took in reviewing the RTBC patch. There were no recent test-only patches until the one I posted. Which is why I posted it. :) Also note that I left the issue at RTBC, which means I didn't think it needed more work.
Re: #82, nah, it's a normal bug because the steps to reproduce it are pretty edgecase-y and specific. Thanks!
Comment #84
acbramley CreditAttribution: acbramley at PreviousNext for Transport for NSW commented@xjm no worries at all! Sorry I must have misinterpreted what you said, thanks for clarifying :)
Comment #85
plachThanks for all your efforts, I manually tested the latest patch and seems to work fine, without introducing regressions, and the additional test coverage looks great. However I'm not completely sure about the proposed solution.
This doesn't look proper to me for two reasons:
view_path
POST parameter that's meant to store the original path for AJAX requests. This is exactly what we need here.Therefore I'd suggest to go back to the solution proposed in #49 that in fact relies on the
view_path
parameter (seeViewAjaxController
lines 125 and 149). I think we should solve the double slash issue mentioned in #50 instead of trying a completely different approach.Of course we would keep all the following improvements the led to #76 :)
Comment #86
xjmWe'll also want to add a test case for the form action/base tag issue (I should have caught that).
Comment #87
plachBtw, also the behavior of
$view->getUrl()
does not make a lot of sense here: if the display doesn't define a path, it will fall back to the first display it can find that does define one. However this display could be totally unrelated to the original one, which would lead again to an unexpected destination on submit (at least without AJAX). Maybe we could just use the current path and skip the view url logic altogether?Comment #88
plachI tried to simply remove the additional slash in
ViewAjaxController
, line 149, and tests are green, which makes me think we are missing test coverage for that and the HEAD behavior is buggy. See https://www.drupal.org/project/drupal/issues/2938524#comment-12552036.Comment #89
VinceThePrince CreditAttribution: VinceThePrince commentedHi! I think I have a similar Issue to this.
https://stackoverflow.com/questions/49709766/contact-form-throws-the-req...
I have created a "Contact storage contact form" within a custom page object. When I submit this contact storage contact form directly from the page it works super. But when I submit it from a block it throws error "The requested page could not be found." More specific this block uses the view module to filter these pages.
You can test this yourself by going to http://mijnverkeersovertreding.be/rechtsbijstand
In the input "Postcode" fill in 1910 and press Apply. A contact form appears once. You can fill it in with random data and when you submit it, it throws error The requested page could not be found on url /views/ajax.
Kr.
Comment #90
acbramley CreditAttribution: acbramley at PreviousNext for Transport for NSW commented@plach You're totally right, I just ran into this situation after adding a new display to a view which was previously just block displays. The new display extended PathPluginBase and therefore was picked up by
$view->getUrl()
and ended up resulting in a fatal due to missing arguments.I'm going to have a crack at using view_path like you've suggested.
Comment #91
acbramley CreditAttribution: acbramley at PreviousNext for Transport for NSW commentedThis should fail. Also cleaned up the deprecated traits.
Comment #93
acbramley CreditAttribution: acbramley at PreviousNext for Transport for NSW commentedAnd the fix. Instead of setting the action always, we can leave it as null for almost all cases as it will then default to the page the form is on. For ajax routes, we override it with an empty string as this seems to ensure the action is set to the path the page is rendered on rather than the ajax path (I'm not sure why this happens, but it works :)).
Still needs tests for the base tag issue mentioned in #85
Comment #95
igalafate CreditAttribution: igalafate at La Drupalera by Emergya commentedI applied the #67 patch and everything works fine for me, but since I have applied the #92 an exposed filter block of my search view is not redirecting to the search page (/search) anymore. When the filter is applied from any page, the url still the same but with the search params. So for example, using my filter block on the homepage I'm getting "/?keys=test" instead of "/search/?keys=test".
Comment #96
esolitosPatch rolled to take care of #67.
Comment #98
AnybodyRTBC +1 for #96
Comment #99
AnybodyWe're using this since a longer period of time on several sites now on 8.5.x and 8.6.x, I think we can set #96 RTBC now.
Comment #100
alexpottDo we need the else here?
This needs to use WebDriverTestBase now - JavascriptTestBase has been deprecated.
Comment #101
remram CreditAttribution: remram commentedThe last patch from #96 working great but one thing is missing. It's not respecting the destination and it's value. In this case if you reset your filter it will remove the destination from the URL und you wont be able to go back to the origin page!
Comment #102
gambryCurrent work - since pretty much the beginning - makes sure form action is empty when views is ran through AJAX.
This does fix this issue according to its title - user is not redirected to a 404 page - however the result is a really weird UX due the reset button not having any AJAX event handler attached. The page is consequently re-loaded when you press the reset button and the meaning of having an AJAX exposed form is completely lost. The user needs to scroll the page to find back the view/form, and that's OK if the view/form exists in page on loading and not for example if it's part of a multi-step AJAX process.
On the other side the JS code states this about why reset is excluded from AJAX behaviours:
So are we only tackling the 404 on reset or the reset not working at all on AJAX?
If the former, than we should state in the IS about the weird UX.
Comment #103
jibranAddressed #100.
Comment #105
jibranTurn out we can't remove #100.1. Fixed reset of the feedback so setting it back to RTBC. @gambry feel free to update the IS.
Comment #107
gambry@jibran I believe what #100.1 means is something like:
I'll update the IS as soon, as I need to re-test my assumptions from #102 ("we are fixing the 404, but causing a potential weird UX") still applies.
Comment #108
maximpodorov CreditAttribution: maximpodorov commentedThe current solution produces invalid HTML code: according to the standard, action attribute must be non-empty if it is specified in the form element.
So +1 for #93.
Or to switch to solutions from #2866386: Assert the view path is set correctly after second ajax request which use ltrim(..., '/') to avoid double slashes.
Comment #109
Anonymous (not verified) CreditAttribution: Anonymous as a volunteer commentedwhat is the status of this bug? I am not as technically adept as most of you contributing in this thread, but I am still having this problem.
It is happening using Drupal 8.6.8 with Empty Page module to produce a blank page without content, and applying two blocks to the empty page.
Upon reset, I get 404 error. Can I "upgrade" or side-grade to 8.6.X dev instead of 8.6.9, or is that not possible?
Is there a fix in place or a workaround?
Comment #110
maximpodorov CreditAttribution: maximpodorov commentedThis patch can be tried. It is the combination of #49 and the patch from #2866386: Assert the view path is set correctly after second ajax request. No tests yet.
Comment #111
IT-CruPatch from #110 fix broken reset button via https://www.drupal.org/project/views_field_formatter embedded views with exposed forms for me.
Comment #112
Anonymous (not verified) CreditAttribution: Anonymous as a volunteer commentedwould the new patch work on 8.6.8?
UPDATE:
can confirm patch is working on 8.6.8 as intended (so far) without the use of views field formatter.
just producing two blocks on an "empty page" and using the patch seems to do the trick
will perform some more views tests and changes.
will report back if testing produces related errors.
huge thanks, maximpodorov @ Comment #110 !
Is reloading of the page upon reset normal behaviour, even though it is AJAX ?
Comment #114
alison#110 works great on 8.6.15, thank you!
(@Careless)
I second that ^^ question!
Comment #115
xaqroxHere's #2820347-110: Exposed filter reset redirects user to 404 page on AJAX view when placed as a block plus the tests from #2820347-105: Exposed filter reset redirects user to 404 page on AJAX view when placed as a block. It applies to 8.7.x and solved this problem for me. However I discovered a *ton* of related issues while tracking this down, conveniently collected in #3055018: URL's generated within AJAX request are re-routed to that AJAX request, that seem to indicate this might be a bigger problem... or just the same mistake repeated in a few different places? Anyway, hope this helps.
Comment #117
xaqroxAnother patch, hopefully passing...?
Comment #118
larowlanBumped into this on a project, thanks for working on it
I realise that constructors are not part of our API, but recently we've been doing this in a BC fashion, e.g. see
We're losing the Html::escape here - are we sure we want that change?
nice!
Comment #119
jurgenhaasConfirmed, #110 works for me too.
Comment #120
stevieb CreditAttribution: stevieb commentedthe patch from #110 fails using composer
Comment #121
fenstratAddresses #118.
Adds the deprecation with a reference to a new CR https://www.drupal.org/node/3066604
Comment #123
acbramley CreditAttribution: acbramley at PreviousNext for Transport for NSW commentedThe failure in #121 is the same issue that we saw all the way back in #87 due to $view->getUrl() returning the url from the first display if the current one doesn't have a path.
Comment #124
acbramley CreditAttribution: acbramley at PreviousNext for Transport for NSW commentedThis patch fixes #123, however I think this will break displays that do have linked displays.
Comment #126
acbramley CreditAttribution: acbramley at PreviousNext commentedAfter chatting about the issue with some colleagues we agreed that it does seem like the functionality of submitting a block's exposed form and being redirected to the linked (or first routed) display is intended and not a bug.
With that in mind, I've rolled back to #121 fixed the test, and added another scenario.
Comment #127
jibranPatch looks good now.
This is non-ajax condition but the comment is about ajax form.
Comment #129
acbramley CreditAttribution: acbramley at PreviousNext commentedFixed #127 and changed to use node url without the leading slash which seems cause the failure in #126
Comment #130
jibranThanks for addressing the feedback this looks good now so setting it to be RTBC.
Comment #131
larowlanComment #132
larowlanCommitted b6b8e0f and pushed to 8.8.x. Thanks!
Published both change records.
The constructor change makes this too disruptive for a backport, so leaving at 8.8.x, sites impacted by this can continue to run the patch at 129 via composer-patches or similar.
Comment #134
esolitosGreat news, thanks everyone!
Comment #136
andreyjan CreditAttribution: andreyjan at FFW commentedThe patch is fixing the issue when there is only one exposed filter.
When there are at least 2 filters, after submitting Reset button you get redirected to the current page with previously applied filters in query parameters (?type=All&field_some_vocabulary_target_id=123&op=Reset) and the following error is displayed:
Drupal\Core\Form\EnforcedResponseException: in Drupal\Core\Form\FormBuilder->buildForm() (line 351 of core/lib/Drupal/Core/Form/FormBuilder.php).
Drupal\Core\Form\FormBuilder->buildForm('\Drupal\views\Form\ViewsExposedForm', Object) (Line: 135)
Drupal\views\Plugin\views\exposed_form\ExposedFormPluginBase->renderExposedForm() (Line: 1238)
Drupal\views\ViewExecutable->build(NULL) (Line: 1391)
Drupal\views\ViewExecutable->execute(NULL) (Line: 1454)
Drupal\views\ViewExecutable->render() (Line: 131)
Drupal\views\Plugin\views\display\Block->execute() (Line: 1630)
I am not sure if I need to open another issue since this one was already committed in 8.8 or just re-opening this one.
Comment #137
larowlan@andreyjan - please open a new issue and link it here 🏆 - thanks
Comment #138
matthieuscarset CreditAttribution: matthieuscarset as a volunteer and commentedJust commenting to let you know this patch #129 unfortunately does not applied on Drupal
8.7
(tested on8.7.7
).Comment #139
Rajab Natshah CreditAttribution: Rajab Natshah at Vardot for Vardot commented#129 is working for Drupal 8.7.8
Waiting for Drupal 8.8.0 :)
Comment #140
bbombachiniThis patch didn't apply on 8.8.0 for me.Thanks @acbramley, I didn't read the whole thread, sorry!
Comment #141
acbramley CreditAttribution: acbramley at PreviousNext commented@bbombachini the fix was committed before 8.8.0 so you don't need the patch :)
Comment #142
anneeasterling CreditAttribution: anneeasterling as a volunteer and at New Valley Media commentedI know this issue is closed and don't expect any action -- I'm just reporting on my experience. On our project, if using exposed filters with ajax turned on, resetting the filters on a view block sends the user to the first page display that was created. I've followed the advice of another commenter to separate the views as a work around. I'd be interested at some point to hear whether others are experiencing the same.
(Leaving this comment here primarily for folks who land here via Google search.)
Comment #143
AaronMcHale@anneeasterling if that is indeed a bug (sounds like it might be), could you open a new issue (if one doesn't already exist), providing as much detail as possible on how to reproduce the problem.
Thanks
Comment #144
liquidcms CreditAttribution: liquidcms commentedSounds a lot like the issue i am having with ver 4.0.0: #3244756: Submit broken when used with AJAX.
Comment #145
jgoodwill01 CreditAttribution: jgoodwill01 commentedRunning into this issue with Version 9.5.0 can anyone help with a patch for current versions of Drupal 9?
Comment #146
alisonSame, haven't confirmed that it's happening on D10, but I'm going to submit a new issue.