ortunado
ortunadoβ€’2y ago

ortunado – 17-21 Nov 8

Could anyone have idea, how to manage querySelectorAll to select all input elements, but not the ones inside another form? For example,
<form class=".form" data-form="Form1">
<div>
<input /> <= This input would like to be selected.
</div>
<div>
<input /> <= This input would like to be selected.
</div>
<form class=".form" data-form="Form2">
<div>
<input /> <= This input would like to NOT be selected.
</div>
<input /> <= This input would like to NOT be selected.
</form>
<input /> <= This input would like to be selected.
</form>
<form class=".form" data-form="Form1">
<div>
<input /> <= This input would like to be selected.
</div>
<div>
<input /> <= This input would like to be selected.
</div>
<form class=".form" data-form="Form2">
<div>
<input /> <= This input would like to NOT be selected.
</div>
<input /> <= This input would like to NOT be selected.
</form>
<input /> <= This input would like to be selected.
</form>
29 Replies
ortunado
ortunadoβ€’2y ago
The easiest would be to use element.closest() but could there be any other way?
Louis
Louisβ€’2y ago
Which inputs do you want here? Can you annotate them please
ortunado
ortunadoβ€’2y ago
Edited the original message. This is the current version with JS, would like to not use element.closest
document.querySelector(`[data-form="${uniqueId}"]`)?.querySelectorAll("input:not([form]), textarea:not([form]), select:not([form]), button:not([form])").forEach(element => {
const closestForm = element.closest(".form");
if (closestForm.getAttribute("data-form") !== uniqueId) {
return;
}

element.setAttribute("form", uniqueId);
});
document.querySelector(`[data-form="${uniqueId}"]`)?.querySelectorAll("input:not([form]), textarea:not([form]), select:not([form]), button:not([form])").forEach(element => {
const closestForm = element.closest(".form");
if (closestForm.getAttribute("data-form") !== uniqueId) {
return;
}

element.setAttribute("form", uniqueId);
});
EvokeMe
EvokeMeβ€’2y ago
const querySelectorWithDepth = (selectorParent, selector, not = 'form') =>
[
`${selectorParent} > :not(${not}) ${selector}`,
`${selectorParent} > ${selector}`,
].reduce((r, v) => r.concat(...(document.querySelectorAll(v) || [])), [])
const querySelectorWithDepth = (selectorParent, selector, not = 'form') =>
[
`${selectorParent} > :not(${not}) ${selector}`,
`${selectorParent} > ${selector}`,
].reduce((r, v) => r.concat(...(document.querySelectorAll(v) || [])), [])
querySelectorWithDepth(`[data-form="Form1"]`, `input`)
querySelectorWithDepth(`[data-form="Form1"]`, `input`)
Louis
Louisβ€’2y ago
Query selector CSS power πŸ’ͺ that's really nice πŸ‘ digging around doing a React 18 upgrade but I probably would've come up with something a bit worse anyway
EvokeMe
EvokeMeβ€’2y ago
And we need remove last small thing. Right now any depth. πŸ™‚
Louis
Louisβ€’2y ago
Beautiful bit of DOM work there
EvokeMe
EvokeMeβ€’2y ago
Also we can merge rules:
const querySelectorWithDepth = (
selectorParent,
selector,
not = ':not(form)',
) =>
document.querySelectorAll(
`${selectorParent} > ${not} ${selector}, ${selectorParent} > ${selector}`,
)
const querySelectorWithDepth = (
selectorParent,
selector,
not = ':not(form)',
) =>
document.querySelectorAll(
`${selectorParent} > ${not} ${selector}, ${selectorParent} > ${selector}`,
)
And form cannot be in form.
Louis
Louisβ€’2y ago
Can you merge query selector selectors like that in the same way you can merge CSS ruleset selectors? I never knew that
EvokeMe
EvokeMeβ€’2y ago
Right.
Louis
Louisβ€’2y ago
Damn, TIL
EvokeMe
EvokeMeβ€’2y ago
<a:7119_Jotaro_Dancing:608310437955502146>
Louis
Louisβ€’2y ago
Haven't had to work with the DOM at a low level for a few years now but that's wicked! Although as an aside, I don't think it's semantically correct to nest forms anyway so πŸ€·β€β™‚οΈ
EvokeMe
EvokeMeβ€’2y ago
Same, now lying in bed a little sick recovered it from memory and docs.
Louis
Louisβ€’2y ago
The days before querySelector were doom and gloom The DOM methods are so powerful but god forbid I have to work with them at that low a level again