Normally, when one or more of the widgets in the exposed form of a view has errors, Views exits the build process for the view and "empties" it.
However, when such a view with exposed widgets is embedded on a page that has one or more unrelated forms "built" before the view is rendered, the same thing happens again. Views is unable to make out the difference between errors caused by its exposed form and by other forms built on the page before it.
I have a sandbox project that illustrates this issue. On downloading and enabling the project, go to /views-example
.
http://drupal.org/sandbox/amarnus/1863012
http://drupalcode.org/sandbox/amarnus/1863012.git
Comment | File | Size | Author |
---|---|---|---|
#76 | 1863020-76.patch | 6.44 KB | Lendude |
#76 | interdiff-1863020-65-76.txt | 1.21 KB | Lendude |
#65 | interdiff-62-65.txt | 2.43 KB | paulmckibben |
#65 | 1863020-65.patch | 6.43 KB | paulmckibben |
#62 | interdiff-60-62.txt | 2.05 KB | paulmckibben |
Comments
Comment #1
amarnus CreditAttribution: amarnus commentedThis patch seems to fix the issue.
Comment #2
dawehnerThank you for providing such helpful information and a patch, so set it to needs review.
Do you currently understand why this behavior is happening, because just by thinking about FAPI etc.
I don't really see what could cause this behavior. Your patch seems to fix the symptoms not the real reason, but yeah sometimes you can't choose.
Comment #3
amarnus CreditAttribution: amarnus commentedFrom what I see, there's nothing wrong with the Form API, really. So, Views assumes that if validation fails in a page with a view having an exposed form in it, then it is probably because of an issue with one or more exposed widgets and cancels the build.
Typically, this assumption holds good for a view with the "page" display type because the content region can just house a view and if there were other forms, they would have to be through blocks in sidebars/other regions. In Drupal by default though, the content is built first before other regions - so it doesn't matter.
However, this assumption is no longer valid when:
In this case, it is no longer clear where the errors are from. If the static error collector -
form_set_error()
was keyed by the form ID or something, we could have done a more elegant check; something along the lines of:Unfortunately though, it doesn't work that way. So, we may have to stick to the crude method as used in the patch.
Comment #4
merlinofchaos CreditAttribution: merlinofchaos commentedThis patch makes sense to me.
Comment #5
dawehnerYeah this makes sense now! It's interesting that you are the first one who see that problem.
Thanks for the code, committed and pushed to 7.x-3.x
Yet another reason why global state can be problematic.
Here are patches for d8 which also includes tests.
Comment #6
aspilicious CreditAttribution: aspilicious commentedSome tests are disabled ;)
Comment #7
dawehnerUps right.
Also rerolled against recent changes.
Comment #9
dawehnerThis time without fails.
Comment #10
dawehner#9: drupal-1863020-9.patch queued for re-testing.
Comment #12
dawehnerJust a rerole.
Comment #13
dawehner#12: drupal-1863020-12.patch queued for re-testing.
Comment #15
dawehner.
Comment #16
dermarioI will try to reroll.
Comment #17
dermarioOk i am "unassigning" from that issues. The reroll is to heavy for me cause of the long time.
Comment #18
jlbellidoRerolled #12 and run test.
Comment #21
YesCT CreditAttribution: YesCT commentedfixing tag. sorry for noise.
Comment #22
dawehner18: drupal-1863020-18.patch queued for re-testing.
Comment #24
deveshpal9 CreditAttribution: deveshpal9 commentedRerolling patch from #18
Comment #26
sunset_bill CreditAttribution: sunset_bill commentedworking on a reroll
Comment #27
sunset_bill CreditAttribution: sunset_bill commentedReroll from #24 (my bad on the patch name)
Comment #28
sunset_bill CreditAttribution: sunset_bill commentedRenamed reroll from patch #24
Comment #29
dawehner.
Comment #31
alansaviolobo CreditAttribution: alansaviolobo commented28: drupal-1863020-28.patch queued for re-testing.
Comment #33
alansaviolobo CreditAttribution: alansaviolobo commentedre-rolling the patch
Comment #35
damiankloip CreditAttribution: damiankloip commentedThanks for the re-roll, and the reminder this issue existed :)
It needed a bit of fixing to bring it up to date, mainly:
- Added a little more to the test assertions
- Created a FormInterface form that has the form error
- Use the #view element to render it page
- Converted the page to a route and controller class
I also rolled the callbacks etc.. into the views_test_data module instead of a new views_test_form module.
Comment #36
damiankloip CreditAttribution: damiankloip commentedSorry - with the correct interdiff.
Comment #37
damiankloip CreditAttribution: damiankloip commentedI also think this is major. This will cause some pretty unexpected behaviour for people.
Comment #40
heddnNeeds a re-roll. Before that though, it might not hurt to validate this is still an issue since it has been a little while since things were worked on here. I'm pretty sure this also needs a backport to D7.
Comment #41
rpayanmComment #43
Nikolay ShapovalovComment #44
mgiffordComment #45
daceej CreditAttribution: daceej at Third and Grove commentedI also faced this issue, and came up with the following patch.
Comment #46
daceej CreditAttribution: daceej at Third and Grove commentedComment #48
catchFirst of all re-rolling with just the tests from #48.
Comment #50
catchPatch was very out of date, slightly better re-roll.
Comment #52
catchTest actually runs properly now, but doesn't fail for me either via simpletest or manually testing with the test module.
Comment #53
catchOK test should now fail and updated version of that patch that makes that test pass.
Didn't check other views tests though so it could break something else.
The FormState:hasAnyErrors() check in HEAD is completely wrong, and there's no way to get the errors without a proper FormState object, so had to add an optional $form_state parameter to ExposedFormPluginBase::renderForm().
Comment #56
alexpottMy previous comment was about another issue. Sorry for the noise.
Comment #57
alexpottDiscussed with @xjm, @tim.plunkett and @dawehner - we decided that this issue is a major issue which you are able to configure a view through the UI that renders the site unusable.
Comment #58
dawehnerIt would be nice to document why we need this second form_state and how this fixes problems.
Comment #60
paulmckibbenI filed a duplicate issue, #2841413, and submitted a patch there. Comparing my patch to #52, my patch may be a little more straightforward, as it does not require a second form_state. Instead, it checks for form_state errors in the renderExposedForm() method and sets the "abort" flag there if it encounters an error. In the ViewExecutable build() method, this allows the removal of the global check, FormState::hasAnyErrors.
My conjecture is that FormState::hasAnyErrors is the wrong method to call, because it is a global check for errors on any form on the page. My patch eliminates the use of that method.
I've created a new patch combining the tests from #52 with my patch. I attempted an interdiff, but interdiff wouldn't work, I guess because the differences are too great. Instead, I have also uploaded a version of my patch without the tests, which is pretty simple.
I look forward to everyone's feedback. Thanks!
Comment #62
paulmckibbenOops, I didn't roll the patch in #60 correctly: I forgot to add the new files from the tests in #52, which is why the patch failed testing.
Here's a rerolled patch with all the tests.
Comment #64
Lendude@paulmckibben fix looks good to me, makes sense and simplifies things and still passes the tests.
Bit of nitpicking:
This could use a comment as to why we are doing it at that point during the execution.
extra white space line can be taken out
this can be taken out, no longer needed per coding standards.
this can be taken out too.
Seems like a copy/paste left over, needs to be updated to something relevant to the current use case.
Comment #65
paulmckibben@Lendude, thanks for the review.
I've implemented your feedback and have uploaded a new patch and interdiff.
Comment #66
LendudeWe have tests, we have a fix, all is green.
Comment #68
paulmckibbenPutting this back in RTBC. I reran tests and they passed. Not sure what happened in #67.
Comment #70
alexpottCommitted and pushed 4fc3756 to 8.4.x and 25d7f11 to 8.3.x. Thanks!
Leaving at patch to be ported so that the D7 views issue can be opened - once it is this issue should be closed.
Removed unused use on commit - nice that these two things are decoupled!
Comment #75
xjmThis also broke HEAD...
https://www.drupal.org/pift-ci-job/597199
Comment #76
LendudeThis fails on 8.3.x because of #2561115: Rollback: Use 'Filter' for exposed filter button text in new views and new installations (instead of 'Apply').
Updated the patch to use the new label.
Comment #77
dawehner+1 for the fix. Too bad we work on multiple things at the same time
Comment #78
alexpottSecond time lucky!
Committed and pushed bfa73c9 to 8.4.x and b4512ef to 8.3.x. Thanks!
Leaving at patch to be ported so that the D7 views issue can be opened - once it is this issue should be closed.
I fixed the unused use again... see #70
Comment #81
alexpottI'm marking this fixed today because I'm triaging the patch-to-be-ported queue. There's been no view 7.x issue created in the past 2 months and the people who worked on this should be credited.
Comment #82
alexpottOpened #2877370: View's build fails when an unrelated form on the same page has validation errors for views d7 backport