A Lightning component can only traverse the DOM and access elements that it created. This behavior prevents the anti-pattern of reaching into DOM elements owned by other components.
It’s an anti-pattern for any component to “reach into” another component, regardless of namespace, because it breaks encapsulation. Lightning Locker only prevents cross-namespace access. Your good judgment should prevent cross-component access within your own namespace as it makes components tightly coupled and more likely to break.
Tip
DOM Access Containment with Lightning Web Components (LWC)
Lightning web components can’t use the window or document global properties to query for DOM elements when Lightning Locker is enabled. For example, use this.template.querySelector() instead of document.querySelector(). The document.querySelector() method isn’t supported for Shadow DOM.
If your org has Lightning Web Security (LWS) enabled instead of Lightning Locker, component access to the DOM is controlled by the browser through Shadow DOM, which is a web standard implemented in web browsers. Inside a component’s sandbox, LWS abides by the developer’s intent for the shadowRoot. An open mode shadowRoot allows JavaScript in the same sandbox to access and manipulate the Shadow DOM. A closed mode keeps internal elements inaccessible, even within the sandbox, preserving encapsulation. LWS makes shadowRoot appear closed to code running outside a component’s sandbox. See ShadowRoot.mode in MDN. Although we don’t recommend using window and document global properties directly, LWS permits access to those properties within an LWC component and its parent hierarchy.
Note
DOM Access Containment with Aura Components
Let’s look at a sample component that demonstrates DOM containment.
1<!--c:domLocker-->2<aura:component>3 <div id="myDiv" aura:id="div1">4 <p>See how Lightning Locker restricts DOM access</p>5 </div>6 <lightning:button name="myButton" label="Peek in DOM"7 aura:id="button1" onclick="{!c.peekInDom}"/>8</aura:component>
The c:domLocker component creates a <div> element and a lightning:button component.
Here’s the client-side controller that peeks around in the DOM.
1({2 /* domLockerController.js */3 peekInDom: function(cmp, event, helper){4 console.log("cmp.getElements(): ", cmp.getElements());5 // access the DOM in c:domLocker6 console.log("div1: ", cmp.find("div1").getElement());7 console.log("button1: ", cmp.find("button1"));8 console.log("button name: ", event.getSource().get("v.name"));910 // returns an error only with Locker, but not with Lightning Web Security11 //console.log("button1 element: ", cmp.find("button1").getElement());12},13});
Valid DOM Access
The following methods are valid DOM access because the elements are created by c:domLocker.
cmp.getElements()
:- Returns the elements in the DOM rendered by the component.
cmp.find()
:- Returns the div and button components, identified by their aura:id attributes.
cmp.find("div1").getElement()
:- Returns the DOM element for the div as c:domLocker created the div.
event.getSource().get("v.name")
:- Returns the name of the button that dispatched the event; in this case, myButton.
Invalid DOM Access
You can’t use cmp.find("button1").getElement() to access the DOM element created by lightning:button. Lightning Locker doesn’t allow c:domLocker to access the DOM for lightning:button because the button is in the lightning namespace and c:domLocker is in the c namespace.
If you uncomment the code for cmp.find("button1").getElement(), you see an error:
1c:domLocker$controller$peekInDom [cmp.find(...).getElement is not a function]