Design a site like this with
Get started

LWC – Access Templates and Methods of child components

Normally closed shadow DOM/root will not allow the access of child component’s DOM. Consider below example:


How can you change styles/add classes OR invoke methods directly in grand-child from main-component? Ofcourse you can have public API methods at each level but this will make it very complicated with many children. So, is there a more simpler and elegant way?

Yes! You can have simple generic registration for all elements in main-component. Then, which ever child component (in any hierarchy) has to be accessed, fire a custom registration event with appropriate details.

Grand child HTML:

    <div id="main" class="main">
        <div class="my-class">
            This is grand-child component body
        <div class="dynamic"></div>

You need a main class which wraps whole content.

Grand child JS:

export default class GrandChild extends LightningElement {
    renderedCallback() {
        if (!this.guid) {
            this.guid = this.template.querySelector('.main').getAttribute('id');
                new CustomEvent('itemregister', {
                    bubbles: true,
                    composed: true,
                    detail: {
                        callbacks: {
                            dynamicData: this.dynamicData
                        template: this.template,
                        guid: this.guid,
                        name: 'c-grand-child'
    dynamicData = (data) => {
        this.template.querySelector('.dynamic').innerText = data;

You need to dispatch custom event with name, guid, template and callbacks. This cannot be done in connectedCallback because in its scope elements will not be created and so elements will be undefined. In renderedCallback, we will be dispatching event only once with help of checking guid.

  1. Template can be used to modify styles or add classes or any similar functionality.
  2. Callbacks will have the exposed functions references
  3. Name and guid are used for registartion

Child HTML

<template for:each={iteration} for:item='it'> 
	<div key={it.mid}>

Child JS:

export default class Child extends LightningElement {
	iteration = [{ mid: '1' }, { mid: '2' }, { mid: '3' }];

Parent HTML


Main component HTML:

<lightning-button label="Add Styles" onclick={addStyles}></lightning-button>
<lightning-button label="Add Data" onclick={addData}></lightning-button>

<div onitemregister={registerItem}>

Main component JS:

    privateChildren = {};
	registerItem(event) {
		const item = event.detail;

		// create key for each child against its name
		if (!this.privateChildren.hasOwnProperty( this.privateChildren[] = {};

		// store each item against its guid
		this.privateChildren[][item.guid] = item;
	addStyles() {
		Object.values(this.privateChildren['c-grand-child']).forEach((element) => {
			element.template.querySelector('.my-class').style.color = 'white';
			element.template.querySelector('.my-class').style.backgroundColor = 'blue';
	addData() {
		Object.values(this.privateChildren['c-grand-child']).forEach((element, index) => {
			element.callbacks.dynamicData('Changing dynamic data => ' + index);

Here, you are using registerItem generic method to register all needed child elements with key as its names. Later you can use the names to access the callbacks and template.

Screenshot before:

Screenshot After:


Join the Conversation


  1. Hi Sasank,

    We have a parent (search page) and a child component (combobox result). We are trying to get the focused div of the child component to close the result based on the focus. Can you please provide your inputs? Thanks.



Leave a comment

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: