As a followup to #1414510: Remove drupal_reset_static for drupal_html_id() when form validation fails, it seems there is a similar bug where you have two forms on a page, and then submit one successfully resulting in a form rebuild (with the page being re-rendered).
There may be other similar duplicate ID bugs as well; this is just the easiest to spot one that I noticed.
Related issues:
#1575060: ajax_html_ids are broken for forms with file element (encoding=multipart/form-data)
#1305882: drupal_html_id() considered harmful; remove ajax_html_ids to use GET (not POST) AJAX requests
Comment | File | Size | Author |
---|---|---|---|
#73 | 1831560-73.patch | 5.8 KB | Lendude |
#73 | interdiff-1831560-71-73.txt | 722 bytes | Lendude |
#71 | 1831560-71.patch | 5.79 KB | mrinalini9 |
#61 | interdiff-1831560-58-61.txt | 864 bytes | acbramley |
#61 | 1831560-61.patch | 5.71 KB | acbramley |
Comments
Comment #1
David_Rothstein CreditAttribution: David_Rothstein commentedHere is a patch with a test that should expose the bug.
Comment #2
David_Rothstein CreditAttribution: David_Rothstein commentedAnd one with a possible fix.
Essentially, I'm pretty suspicious about the code in the form API which resets HTML IDs when a form is being processed, so I think we might just consider removing it.
It was added a long time ago in #111719: FAPI fails to check auto-generated IDs for uniqueness - XHTML validation fails. and as the code comments explain, its purpose is to avoid needlessly incrementing IDs when a form is built twice on the same page request but only displayed once. However, that seems like an unusual and unideal situation to begin with (especially with the current form API), and even if it ever does happen the worst we get is some needlessly incremented IDs, which these days isn't a big deal really since you already can't rely on auto-generated IDs having a specific value in CSS and JavaScript anyway.
So, let's see what the testbot thinks about totally removing that code.
Comment #3
sunClarifying issue title based on #2
Comment #5
fagooh, I just realized I opened a duplicate: #2034631: Remove drupal_reset_static for drupal_html_id() during form processing
Besides some tests would need to be addapted I'm not sure it's a simple fix to roll out for d7 though, as it will change HTML-IDs for some folks.
Here is my post from there:
So right now, form API resets drupal_html_id() IDs each time a form is processed (and there are no validation errors, thanks to #1414510: Remove drupal_reset_static for drupal_html_id() when form validation fails ). However, this is problematic if
- forms a processed during an ajax request. We do a lot of work to add in all past html IDs, increase the payload of ajax requests to have them, and then we reset the html IDs before the form is rendered? That's dumb.
- if multiple forms are used on page and some of them are always processed - this is a supported form API feature and used by exposed filter forms of Views:
So once this feature is used you have a reset of your html IDs somewhere in the rendering pipeline (where the exposed views form is displayed), what in my case resulted in duplicate IDs and consequently in bizarre JS errors due to wrongly merged AJAX command settings (those are keyed by a now not more unique ID).
So this creates troubles, and that "just" for being nice and not unnecessarily incrementing element IDs? Furthermore, unnecessarily incrementing the IDs will only happen if you process forms behind the scenes what is generally not best practice as you should use API functions instead.
So let's remove that troublesome reset.
Comment #6
fagoIt's about HTML-ids not $form_id though - so updating title.
Comment #7
fagoAs tests have shown this is not just for being nice - I guess the comment was not clear to me here. So this patch makes sure we keep the html IDs during rebuilds, but instead of just resetting we better revert them to the previous state.
Comment #9
fagoPatch of #7 was for Drupal 7. This one is for Drupal 8.
Comment #10.0
(not verified) CreditAttribution: commentedUpdated issue summary.
Comment #11
holdmann CreditAttribution: holdmann commentedPatch of #7 works not as expected.
If we create views with 2 exposed forms, which of that has similar element id with different values (f.g. two node types use two taxonomy vocabularies, each of them consists brands. So field identifier obviosly should be brand_id or similar...).
All time form is submitted user will see 'An illegal choice has been detected. Please contact the site administrator.' message, despite of his selection.
This srting always returns true (form.inc line 1348)
elseif (!isset($options[$elements['#value']])) {
because $options consists elements of another form. But i haven't no idea why.
Any suggestions?
Comment #12
guschilds CreditAttribution: guschilds commentedPatch #7 worked for me with Drupal 7.
I had multiple exposed forms on the same page and having the same item in multiple forms was causing problems. 'drupal_html_id' was being reset between each form, so I was not able to use it to create unique item IDs. With this patch, I was able to and my the forms work as expected.
Keeping the status as "Needs work" due to failed testing.
Comment #13
tim.plunkettComment #14
Devin Carlson CreditAttribution: Devin Carlson as a volunteer commentedThe patch in #7 works for me as well. Attaching a reroll; I'll move back to D8 after a test run.
The changes to autocomplete in Drupal 7.39 surfaced this issue in Drupal Commons. Commons provides a "browsing widget" which is a set of jQuery UI tabs, where each tab contains an AJAX view displaying nodes of a specific content type. Each content type view displays a form in the header which allows users to create a new node of the same type.
Many of the forms contain the same fields (title, tags, associated organic groups) which all receive the same IDs. While this is invalid HTML, with the autocomplete changes, having one or more autocomplete-enabled fields now results in an
Uncaught TypeError: Cannot read property 'form' of undefined
error which causes all JS to fail.Comment #16
Devin Carlson CreditAttribution: Devin Carlson as a volunteer commentedComment #17
dawehnerThis is now about the call to
Html::resetSeenIds();
Comment #20
acbramley CreditAttribution: acbramley at Department of Justice & Community Safety, Victoria commentedJust tracked this issue down after an accessibility review.
Caused by 2 views exposed filters on the same page. During \Drupal\Core\Form\FormBuilder::processForm of the second form the Html::resetSeenIds() call clears the "edit-actions" id used as the container id for the actions element.
Comment #21
acbramley CreditAttribution: acbramley at Department of Justice & Community Safety, Victoria commentedHere's a failing test. Let me know if this is completely in the wrong place!
Comment #22
andypostComment #24
acbramley CreditAttribution: acbramley at Department of Justice & Community Safety, Victoria commentedFollowing what the patch in #9 was doing (moving the reset into rebuildForm) I've whipped up this. It makes the test in #21 pass and the rest of the form builder tests pass but lets see what else breaks.
Comment #26
acbramley CreditAttribution: acbramley at Department of Justice & Community Safety, Victoria commentedFixes test failures
Comment #28
sylvainar CreditAttribution: sylvainar commentedHey !
I'm currently experimenting the same problem on a project I'm on. The patch seems great but it doesn't pass on 8.3, the version I'm using. I'll try to modify it in order to import your tests too.
Is this is going to be merged? Few people actually seems to care, but this problem is a real accessibility killer…
Comment #29
mvwensen CreditAttribution: mvwensen commentedManually applied patch #26 onto the 8.3.x branch, recreated a patch that applies on 8.3.x. Please review and fix if necessary!
Comment #31
mvwensen CreditAttribution: mvwensen commentedNew patch added, let's see if the tests work this time.
Comment #32
acbramley CreditAttribution: acbramley commented@mvwensen nice! Can you provide an interdiff please?
Comment #33
mvwensen CreditAttribution: mvwensen commentedHere you go!
Comment #35
CRZDEV CreditAttribution: CRZDEV at Metadrop commentedAdding patch for D7 as a D8 backport.
Patch #14 was working but it was generating some troubles with contrib modules like captcha.
Can anyone review please? thanks!
Comment #37
tunicNot sure but it seems disk was full:
Trying to enqueue it again.
#EDIT: First try yes, but second try disk was ok. Two errors detected, see https://www.drupal.org/pift-ci-job/800872.
Comment #38
CRZDEV CreditAttribution: CRZDEV at Metadrop commentedFound some troubles with complex form like having nested paragraphs, here goes new version of the patch moving "drupal_html_id" reset to drupal_rebuild_form function.
Thanks Tunic for that test evaluation.
Comment #39
CRZDEV CreditAttribution: CRZDEV at Metadrop commentedComment #40
borisson_I know that this commend is just copy pasted, but it should be reflowed to be closer to 80 cols. It should also start with a capital letter, meaning that the first sentence should be different (because the we can't have the function start with a capital).
The indentation here looks off.
Comment #41
CRZDEV CreditAttribution: CRZDEV at Metadrop commentedborisson_ here goes new patch with the suggested improvements, thanks for the review.
Any other suggestion is welcome.
Comment #42
borisson_Awesome, looks good!
PS: Next time, please provide an interdiff as well as a patch to make reviewing easier.
Comment #43
CRZDEV CreditAttribution: CRZDEV at Metadrop commentedSure, thanks!
Comment #44
catchThis should have test coverage if at all possible. Looks like there's rough tests already on the issue that didn't make it into the final patch.
Comment #45
tim.plunkettAlso, the patches since #31 have been for D7.
Hopefully the work done since then can be salvaged and put back into a workable D8 patch.
Comment #46
catch8.x code lives at https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Component%21Util...
There's still #2897377: $form['#attributes']['data-drupal-selector'] is set to a random value so can't be used for its intended purpose and #1090592: [meta] Use HTML5 data-drupal-* attributes instead of #ID selectors in Drupal.settings are both open related to this.
Comment #48
alzz CreditAttribution: alzz at Metadrop commentedApplied #41 patch on 7.56 and works. As it was moved to "Reviewed & tested by the community" and the moved to "Needs work" for Drupal 8 I think we should include this fix in Drupal 7 and keep going with the Drupal 8 approximation.
Comment #49
harsha012 CreditAttribution: harsha012 as a volunteer and commentedre-rolled the patch to 8.5.x
Comment #51
harsha012 CreditAttribution: harsha012 as a volunteer and commentedfixed the minor glitch
Comment #52
andypostLooks nice
Comment #53
Gábor HojtsyHow can we be sure that there are not unintended side effects? Are we testing some (other) scenarios of form ID names (already)?
Minor: whitespace issues in these two hunks.
It is about elements with the same name, not necessarily the same element, right? Eg. they could be entirely different element types, etc.
Comment #56
Couttsy CreditAttribution: Couttsy commentedI'm experiencing this problem now and it's a real accessibility killer. Is there any hotfix that I can use to resolve it? I'm on the current version of Drupal 8. For how long this issue has been open it really makes me think nobody cares about this problem.
Comment #57
acbramley CreditAttribution: acbramley commented@Couttsy there are patches in this issue that you can use to fix it. E.g the patch in #51.
Comment #58
acbramley CreditAttribution: acbramley at PreviousNext commentedRerolled, fixed whitespace and comment issues from #53 and fixed deprecated calls to getMock()
Comment #61
acbramley CreditAttribution: acbramley at PreviousNext commentedFixed failure in #58, it looks like the ids went back to their previous
edit-type
id, but given that it's obviously flakey to rely on the id, I've changed it to use the select label.Comment #62
larowlanLooks good
Comment #64
LendudeRandom media fail, back to RTBC
Comment #65
LendudeThis is blocking a bug in Views, #2894747: Views hardcodes exposed filter block form ID's which breaks AJAX when the same form is shown multiple times on one page
Comment #66
catchPre-existing issue with the comment, or maybe due to the context change? The condition is that the form doesn't have any errors, but the comment is 'in case of errors'.
Comment #68
Lendude@catch I think the comment is correct, if somewhat clumsily worded. This comes from #1414510: Remove drupal_reset_static for drupal_html_id() when form validation fails where there are screenshots showing that the reset of ID's causes a break when done when there are errors.
So the comment should probably be something along the lines of "We only reset HTML ID's when there are no validation errors as this can cause ID collisions with other forms on the page otherwise.", but that should probably be follow-up?
Comment #69
catchPatch no longer applies. Ideally whoever re-rolls this could also make the comment change suggested in #68, or whoever commits this could do it on commit. Don't think we need a separate issue really but also don't want to hold this up any more.
Comment #70
mrinalini9 CreditAttribution: mrinalini9 at Srijan | A Material+ Company for Drupal India Association commentedComment #71
mrinalini9 CreditAttribution: mrinalini9 at Srijan | A Material+ Company for Drupal India Association commentedRerolled patch for 9.1.x along with the changes suggested in #68, please review.
Comment #72
acbramley CreditAttribution: acbramley at PreviousNext commentedBack to RTBC
Comment #73
LendudeQuick clean up for the comment being over 80 chars, leaving RTBC
Comment #77
catchCommitted/pushed to 9.1.x and cherry-picked through to 8.9.x, thanks!
Comment #79
Krzysztof Domański#3169918: data-drupal-selector isn't stable since 8.9.0
HTML IDs have been changed. Do we need a Change Record?