I need get elements from Shadow DOM and change it. How i can do it?
<div>
<input type="range" min="100 $" max="3000 $">
</div>
I need get elements from Shadow DOM and change it. How i can do it?
<div>
<input type="range" min="100 $" max="3000 $">
</div>
You cannot access a Shadow DOM created by the browser to display a control, that is called a #shadow-root (user-agent) in the Dev Tools. <input> is one example.
You can only access open custom Shadow DOM (the ones that you create yourself), with the { mode: 'open' } option.
element.attachShadow( { mode: 'open' } )
Update
It's true for most UX standard HTML elements: <input>, <video>, <textarea>, <select>, <audio>, etc.
Here is an example:
var container = document.querySelector('#example');
//Create shadow root !
var root = container.createShadowRoot();
root.innerHTML = '<div>Root<div class="test">Element in shadow</div></div>';
//Access the element inside the shadow !
//"container.shadowRoot" represents the youngest shadow root that is hosted on the element !
console.log(container.shadowRoot.querySelector(".test").innerHTML);
Demo:
var container = document.querySelector('#example');
//Create shadow root !
var root = container.createShadowRoot();
root.innerHTML = '<div>Root<div class="test">Element in shadow</div></div>';
//Access the element inside the shadow !
console.log(container.shadowRoot.querySelector(".test").innerHTML);
<div id="example">Element</div>
I hope this will help you.
To answer (a generalized version of) the OP question:
It feels like the shadow root API is still lacking (or I just don't know it well enough). But it basically renders querySelectorAll somewhat useless, in that querySelectorAll will not actually get all matching elements anymore, since it simply ignores all ancestors in shadowRoots. Maybe there is an API that fixes that, but just in case there is not:
Here is a simple function that recursively iterates all shadowRoots and gets you all matching elements on the page, not just those of a single shadowRoot.
/**
* Finds all elements in the entire page matching `selector`, even if they are in shadowRoots.
* Just like `querySelectorAll`, but automatically expand on all child `shadowRoot` elements.
* @see https://stackoverflow.com/a/71692555/2228771
*/
function querySelectorAllShadows(selector, el = document.body) {
// recurse on childShadows
const childShadows = Array.from(el.querySelectorAll('*')).
map(el => el.shadowRoot).filter(Boolean);
// console.log('[querySelectorAllShadows]', selector, el, `(${childShadows.length} shadowRoots)`);
const childResults = childShadows.map(child => querySelectorAllShadows(selector, child));
// fuse all results into singular, flat array
const result = Array.from(el.querySelectorAll(selector));
return result.concat(childResults).flat();
}
// examples:
querySelectorAllShadows('td'); // all `td`s in body
querySelectorAllShadows('.btn') // all `.btn`s in body
querySelectorAllShadows('a', document.querySelector('#right-nav')); // all `a`s in right menu