I am having a parent component called providerHome and it has one lightning combo box.
Inside providerHome I have child component as dynamicElement and inside dynamic Element I am loading multiPicklist
ProviderHome –> dynamicElement –> multiPicklist
On onchange event of providerHome combobox I want to pass some values for validation so I am using this approach
in providerHome.js
picklistHandleChange(event) {
const dependantValues = {
controllerEvent: event.target.name,
inputDesc: this.inputDesc
};
this.template
.querySelector("c-dynamic-element")
.constructMultiDropDown(dependantValues);
}
Inside dynamicElement.js
@api constructMultiDropDown(values) {
// console.log("values :>> ", JSON.stringify(values));
this.template
.querySelector("c-multi-pick-list")
.multiDropDownConstruct(values);
}
In multiPickList.js
@api
multiDropDownConstruct(values) {
console.log("Reached grand child:>>",values);
}
From parent –> child its working fine but from Child –> grand child I am always getting error.
I cant go for @api approach as this dynamic element component is responsible for loading all lightning components like lightning-input,lightning-combobox etc
I tried this also and not working
in providerHome.js
picklistHandleChange(event) {
const dependantValues = {
controllerEvent: event.target.name,
inputDesc: this.inputDesc
};
this.template
.querySelector("c-dynamic-element")
.querySelector("c-multi-pick-list")
.multiDropDownConstruct(dependantValues);
}
Error
I tried by getter/setter. When the page loads I am getting console.log in grand child. After that if i change the drop down in parent component , getter/setter in grand child is not getting fired . Not sure what is the issue
In child(dynamicElement.js)
@track childDependant = "Initialized";
@api constructMultiDropDown(values) {
console.log("Fired becoz of parent combobox change");
this.childDependant = "Changed";
}
HTML
<template>
<c-multi-pick-list
label={attrs.label}
options={attrs.options}
disabled={attrs.disabled}
showclearbutton="true"
showfilterinput="true"
showrefreshbutton="true"
from-parent={childDependant}
></c-multi-pick-list>
</template>
In grand child (multiPicklist.js)
_dependantValue;
@api get fromParent() {
console.log(this._dependantValue, "this._dependantValue");
return this._dependantValue;
}
set fromParent(value) {
this._dependantValue = value;
}
Actually I am using only one template to render multiple fields
<template for:each={dataForDynamicComponentCreation} for:item="item">
<div key={item.requiredKey} class="slds-size_1-of-4">
<div class="slds-m-around_x-small">
<c-dynamic-element
attrs={item.attributes}
tag={item.componentDef}
></c-dynamic-element>
</div>
</div>
</template>
So if a lightning-input is created it will created inside <c-dynamic-element>
and similarly all will be created inside </c-dynamic-element>
So in order to find out the method inside Multipicklist component I have to do querySelectorAll, loop through it and find out the place where multi picklist is located and then fire. Instead I just did queryselector so always it searched for method in first component(lightning-input) instead where multipicklist is located.
Best Answer
I have tried a sample code to pass data from
parent ===>> child===>> grandchild
in Lightning Web Component.I have used two ways to do so. The first is @api property and another one using querySelector. Both works fine. The below code pass a value from parent to child and then child to grandchild.
parentComponent.html
parentComponent.js
childComponent.html
childComponent.js
grandChildComponent.html
grandChildComponent.js
Demo Video