Decision Use data-drupal-selector to target form elements in JavaScript
acceptedClasses and IDs are unstable JavaScript targets in Drupal, while data-drupal-selector is a stable hook provided by the Form API.
Decision
When JavaScript needs to target an element rendered through Drupal's Form API, select it by its data-drupal-selector attribute instead of a class or an ID.
Drupal adds data-drupal-selector to every form and to every form element that has an ID. The attribute exists to provide a selector usable by JavaScript, because the ID cannot be relied on. In practice this covers entity forms, configuration forms, views exposed filters, the search block, and the forms inside Media Library and Layout Builder dialogs.
Classes and IDs fail as JavaScript hooks for different reasons:
- IDs must be unique, so Drupal appends suffixes such as
edit-title--2when a form or element renders more than once on a page. - On AJAX requests, Drupal appends random suffixes to ids such as
edit-title--aB3-cD_eFghto ensure uniqueness. - Classes are owned by the theme layer, and switching the theme, or functionality meant to work across a user facing theme and an admin facing theme, can break your class-based selectors.
// Avoid: breaks when the ID gets a suffix on rebuild.
document.querySelector('#edit-title');
// Avoid: breaks if the active theme overrides the relevant template / pre-processor and changes the class
document.querySelector('.form-item-title');
// Prefer: stable across rebuilds, themes, and duplicate renders.
document.querySelector('[data-drupal-selector="edit-title"]');
Exceptions
- Accessibility wiring such as
label[for]andaria-describedbymust keep referencing IDs. That is referencing an ID, not selecting by it in JavaScript. - When third-party libraries or contrib modules only expose class-based hooks, classes can be used as selectors for these elements.
- Older Drupal convention used
js-*prefixed classes. Whendata-drupal-selectorattributes are not available, butjs-*classes are available, preferjs-*classes before presentational classes.
Consequences
- JavaScript keeps working when a form renders more than once on the same page. This removes a common source of regressions in views exposed filters and dialog-based UIs.
- Selectors document their own intent. A
[data-drupal-selector]selector marks a functional dependency, while a class only describes presentation, making it clear which parts of the markup JavaScript relies on.
Additional Resources
- Change record: HTML IDs are now randomized for AJAX responses, the official guidance introducing
data-drupal-selectoras the replacement for ID selectors in JavaScript. - Change record: Changes to generation of data-drupal-selector attribute for form elements, which describes how the attribute is generated and how to set it explicitly.