0

I'm using the following in Javascript functions in LWC "var uiSection = this.template.querySelector('[data-id="sidebar"]');" to find a UI element with data-id=sidebar. This works ok when exists within the same in the LWC. However if I call "var uiSection = this.template.querySelector('[data-id="sidebar"]');" from an onclick in a child it can't find it. The following is a pseudocode of my code

Markup

                    <div class="expander active" data-id="expander-control" onclick={divClickHandler} ></div>
                    <ul class="sidebar" data-id="sidebar">
                        <template for:each={stations} for:item="station">
                            <li class="active stationItem" key={station}>
                                <div class="item-header">
                                    <div class="label">{station.Name}</div >
                                </div>  
                                <template if:true={station.Station_Assets__r}>
                                    <div class="item-content">
                                        <template for:each={station.Station_Assets__r} for:item="asset">
                                            <ul class="typelist" style="max-height: 156px;" key={asset.Id} onclick={assetClickHandler}>
                                                <li>
                                                    <span key={asset.Id} id={asset.Id} data-id={asset.Id} class="assetType" data-classname="assetType" onclick={assetClickHandler}>{asset.Name}</span>
                                                </li>
                                            </ul>
                                        </template>     
                                    </div>    
                                </template>   
                            </li>
                        </template>
                    </ul>
                </div>

JS Functions

divClickHandler(event, component) {
    var uiSection = this.template.querySelector('[data-id="sidebar"]');
    if(uiSection){
        console.log('Found section');
    }else{
        console.log('Not Found');
    }
 }  

assetClickHandler(event, component) {

    var uiSection = this.template.querySelector('[data-id="sidebar"]');
    if(uiSection){
        console.log('Found section from asset');
    }else{
        console.log('Not Found from asset');
    }
}  

...

My call to divClickHandler finds the UI with the data-id ok. My call to assetClickHandler does not find it. Should this.template.querySelector not work across the whole DOM or does it only work in the immediate template? To access the same UI element in a child what would be the best way to do this? Any tips would be appreciated.

1
  • Hi. LWC uses shadow DOM and so one component cannot see the DOM for another. This is by design. You can read more in the documentation.
    – Phil W
    Commented Sep 13, 2021 at 18:37

1 Answer 1

0

this.template.querySelector will only access the DOM that the component owns, excluding children component(s) due to the nature of shadow DOM.

however, for nested templates with template directives, you should be able to access the dom with selectors, as you are doing.

I did a quick copy pasta version f your code, I am unable to reproduce what you are experiencing, maybe you can update it and share a link in your post with the issue?

Your component in Web.dev

5
  • Hi @phil w and glls, thank you for your help. One thing I may have mis-explained is that the markup is all in one component. There is no child component. What I meant was there are different layers of <template> within the component. By child I meant there are <template>'s within <template>. Does the same logic apply in terms of shadow DOM for nested <template>'s also as opposed to nested components? Maybe the same issue applies? Thanks again for your help.
    – RedQueries
    Commented Sep 13, 2021 at 21:26
  • 1
    if the templates, are just nested templates within the same component, the DOM should be accessible iirc, as it is owned by the same component. If you have a template directive that prevents rendering of certain sections based on x conditions, that might be the actual issue.
    – glls
    Commented Sep 13, 2021 at 21:44
  • No. The template elements are not separate DOMs. Have you tried adding the "ul" element to the query selector, or even the .sidebar class, rather than having just the unadorned attribute selector?
    – Phil W
    Commented Sep 13, 2021 at 21:48
  • It is true that if the element is not shown due to an if:true/false expression then it does not get rendered to the DOM and you will get undefined.
    – Phil W
    Commented Sep 13, 2021 at 21:50
  • @RedQueries - shared a link for you in the post. feel free to update and share in your post
    – glls
    Commented Sep 13, 2021 at 22:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .