Problem/Motivation
When form validation errors occur in Views exposed forms when the View has AJAX enabled, the error messages are not displayed.
Steps to reproduce
Create a view with an exposed filter on the author
Enable ajax on the view
Use the view and submit the form with a non-existent username
No error message is shown.
Proposed resolution
Prepend status messages in the views ajax controller.
Original report
The applied validation error messages are not shown for a view exposed filter on failure when "Ajax" is on.

the messages are displayed again on next page load.
There is an older issue opened for Drupal 7
https://www.drupal.org/node/1833322
Recommended solution:
function MODULE_views_ajax_data_alter(&$commands, $view) {
$commands[] = ajax_command_prepend($commands[0]['selector'], theme('status_messages'));
}
Is the correct way to solve the problem or solution should be implemented in views module itself ?
| Comment | File | Size | Author |
|---|---|---|---|
| #70 | interdiff-2977785-68-70.txt | 856 bytes | acbramley |
| #70 | 2977785-70.patch | 5.9 KB | acbramley |
Comments
Comment #2
cilefen commentedComment #5
berdirProof of concept, this works, but not sure about the IEF part. Always the question where to put code that is integrating two modules, but right now, without that, you get duplicated messages and they are also quite challenging to theme inside the typical exposed form, not a lot of room. And forms tend to be short and typically on top of the page.
Also, the IFE thing also happens on non-ajax views, so that could be fixed separately from this. Didn't find an existing issue for views + IEF though.
Screenshots. No screenshot when ife is disabled, but then you simply get nothing until the refresh.
HEAD, with IFE enabled:

HEAD, after page refresh (with and without IFE)

With patch, without the IFE exclude, also HEAD without ajax

With patch including IFE exclude.

Comment #6
lendudeWhile printing the messages makes sense to me, I'm just curious how it looks when there are existing messages on the page and you get a new error message. Can we somehow use the Javascript Messaging API #77245: Provide a common API for displaying JavaScript messages ?
The IFE fix feel a bit like a band-aid, it seems that IFE + AJAX is not 100% (just getting this from the comments by @dmsmidt in the above issue, didn't do any research to verify this). But as a band-aid it makes sense...
Comment #7
berdirI don't feel like this is the issue to start using that API? I just replicated the existing default ajax behavior, when you only return a return array then messages are automatically prefixed, exactly like this. See \Drupal\Core\Render\MainContent\AjaxRenderer::renderResponse(). It's only when you return an ajax response that you need to take care of that yourself.
Yes, the IFE exclude is certainly a band-aid, but ajax is not the only problem. The problem is that views exposed forms have this really weird behavior where they store label information in a separate structure and only set them in pre_render on the form elements, then IFE sees no label and bails out in \Drupal\inline_form_errors\FormErrorHandler::displayErrorMessages(). If the label would be set, you would instead see the usual "2 errors found on: LabelA, LabelB" message on top, not the duplicated validation error.
And IMHO even if that would work, it wouldn't make that much sense in this context, so I think opting out makes sense. Then again, I proposed the same for the login form which is IMHO weird with IFE, but wasn't able to convince others :)
Comment #9
agileadamFor what it's worth, Berdir's patch in #5 is working well for me on 8.7.11.
Comment #10
hardik_patel_12 commentedRe-rolled for D8.9.x
Comment #12
kishor_kolekar commentedI've re-rolled patch for 9.1
Comment #13
acbramley commentedWorks really well, just needs tests! I'll look to add some tomorrow.
Comment #14
acbramley commentedWorking on tests
Comment #15
acbramley commentedHere's #12 with a test and test-only patch (also the interdiff)
Comment #16
acbramley commentedComment #18
amjad1233Micro-optimisation:
Was wondering if sprintf() can be used to add $dom_id
Comment #19
acbramley commentedTest-only failed as expected. Back to NR
Comment #20
sam152 commentedLooks great, just a few questions re: unrelated changes.
Formatting changes?
Maybe also out of scope?
Comment #21
acbramley commentedYeah let's remove those changes.
Comment #22
sam152 commentedLooks good to me. I've read @Berdir's comment on opting out here. Not sure how it was managed elsewhere, but it seems fine that if someone needed this feature a follow-up could be opened to address it.
Comment #23
acbramley commentedHere's the 8.9 patch.
Comment #24
lendudeDo we need test coverage for this?
Can we use something other then assertWaitOnAjaxRequest()? Seems like we can use waitForElement here which is less brittle.
Comment #25
jibranHow can we test #24.1?
I agree #24.2 can be changed.
These two can be combined and
waitForElement('div[aria-label="Error message"]')can be used.Comment #26
deepak goyal commentedHi @jibran
Updated patch please review.
Comment #27
jibranThanks!
Please revert this change.
Comment #28
jibranOn second thought, I don't think we need tests for #24.1.
Comment #30
mrinalini9 commentedReverted changes from patch #26 as mentioned in #27, please review.
Comment #32
mrinalini9 commentedFixing test case failure issue in #30, please review.
Comment #33
jibranGreat!
Comment #34
quietone commentedI read the Issue Summary and skimmed the issue and the patch. I think the proposed resolution in the IS should match the solution in the patch, and it doesn't seem like it does. The IS contains a before screenshot, does it need an after screenshot? The IS says there is an issue for Drupal 7, is there any recommendation here for helping to finish that issue? Adding tag for updating the IS based on those questions.
And during my skim of the patch I notice 2 nits.
Can we add this in alphabetical order? There are other entries in the use statements using \Drupal\Core\Ajax\... and this would fit nicely there.
greater than 80 characters
Comment #35
hardik_patel_12 commentedFixing 2 nits , use statements in alphabetical order and greater than 80 characters.
Comment #37
hardik_patel_12 commentedRandom failure back to need review.
Comment #38
snehalgaikwad commentedAccording to the issue summary I reproduced this issue on local. Error message was not shown for exposed filter in view with AJAX. Patch #35 applied cleanly. Now error message is shown for exposed fields.
Comment #40
ravi.shankar commentedHere I have fixed a coding standard message of patch #35.
Looks like an unrelated test failure, so making it RTBC as per comment #38.
Comment #41
larowlanCan you elaborate on what the reasoning was here - cheers
Comment #45
kim.pepperComment #49
acbramley commentedAdded coverage for inline form errors, this fails without the disable_inline_form_errors line. Also fixed the expected message, added :void
Comment #50
acbramley commentedIt seems like all failures similar to #49 in core are already ignored so this is my best guess at something that will work for us.
Comment #52
sourabhjainComment #53
sourabhjainFixed the error in #53 patch.
Please review.
Comment #54
tanuj. commentedTried to fix CCF on #53
Comment #55
lendudeThe new tests got lost in #53, please add them back in
Comment #56
prem suthar commentedAdd the Tests As Per #55 Suggestion. try To Fix failed test.
Comment #57
acbramley commentedThe correct fix is to not let ViewAjaxControllerTest return NULL for renderRoot. There was already a mock for
renderwhich isn't even called in that test, so we just replace that mock withrenderRootComment #58
smustgrave commentedConfirmed the issue following the steps in the issue summary.
Using patch #57 I now get an error.
There are no users matching "asfsd".
Changes look good.
Comment #59
larowlanShould we be using ::executeInRenderContext like we do on 193-201 just in case something leaks metadata?
Comment #60
ameymudras commentedComment #61
ameymudras commentedComment #62
ameymudras commentedComment #64
acbramley commentedI think we need to pop the context here and apply the cacheable metadata, but then what would we apply that to?
However, looking at other usages of status messages in AJAXy type scenarios in core we never use executeInRenderContext.
See AjaxRenderer, ManagedFile, ViewsFormBase
So I think we're good with #57.
Comment #65
smustgrave commentedThink I agree with @acbramley
If there's room for refactoring the standard of AJAX status messages maybe that should be a follow up?
Comment #67
larowlanViewsFormBase is wrapped by
\Drupal\views_ui\Form\Ajax\ViewsFormBase::ajaxFormWrapperas far as I can see, and that does the executeInRenderContext dance.Status messages is placeholdered so in Big pipe scenarios could require JS, additionally anyone could in theory alter #cache/#attached in a hook_preprocess_status_messages.
However looking
\Drupal\Core\Ajax\CommandWithAttachedAssetsTrait::getRenderedContentit looks like if you pass in an array it will take care of getting the attached libraries and rendering, so can we just pass['#type' => 'status_messages']as the content to the prepend command? Would simplify things a lot I think so it's worth a shot I think.Comment #68
acbramley commented@larowlan that does work! So much cleaner.
Comment #70
acbramley commentedNeed to mock
getInfoon the element manager now since way down the stack that is called with the new method of passing in an array.Comment #71
smustgrave commentedRetested following steps in issue summary.
Patch #70 still addresses the issue.
Comment #72
larowlanCan we get an answer for #41 or alternatively @Lendude can you confirm they're not needed?
Comment #73
larowlanAdding issue credits
Comment #74
lendudeI think we already have it when
pageTextContainswas changed topageTextContainsOnce, basically what I was looking for was something that would fail if somebody removed$form['#disable_inline_form_errors'] = TRUE;, and if the comment above that line is correct, that should do the trick.So this looks good to me, nice work all!
Comment #75
larowlanComment #78
larowlanCommitted to 10.1.x and backported to 10.0.x
Queued a test run for 9.5.x, will backport there if it passes.
Comment #80
larowlan9.5 run came back green, backported to 9.5.x - marking as fixed 💪
Comment #82
kostiantynIs there a patch available for drupal 8.9? I can't seem to find one. The one for version 9 isn't working for me.