7

I have 3 components as child, parent and grandparent. From child component, I dispatch an event using bubbles: true, composed: true, intimating the grandparent to refresh. In the grandparent, I use refreshApex and get the updated data from the back-end (all this verified).

However, the updated data is not passed to it's child and grandchild components.

Any idea how I can achieve this? I need to get the updated data in child and grandchild components.

Code Snippet: grandParent.js

export default class GrandParent extends LightningElement {
   lstMyData = [];
   wiredResult;
   @wire(GET_DATA)
   myList(result){
      this.wiredResult = result;
      if(result.data){
          this.lstMyData = result.data
      }
   }
   
   handleNewFeedback(event){
        return refreshApex(this.wiredResult);
   }
}

grandParent.html:

<template>
  <div class="header_bgcolor">
    My Contacts Data
    <template for:each={lstMyData} for:item="contactData">
       <c-each-contact-data key={contactData.recId} obj-contact-Data={contactData} onfeedback={handleNewFeedback}></c-mbo-contact-objective>
    </template>
    </div>
</template>

parent.js

export default class Parent extends LightningElement {
      @api objContactData;
      myContactData;
      showFeeback = false;
      connectedCallBack(){
        this.myContactData = Object.assign({},this.objContactData);
      }
      showFeedbacks(event){
        this.showFeeback =  !this.showFeeback;
      }
}

parent.html

<template>
    <div for:each={myContactData} for:item="contactData" key={contactData.recId}>
        <p>Name : contactData.Name</p>
        <p onclick={showFeedbacks}>Feedback Count : contactData.countOfFeedbacks</p>
        <div if:true={showFeeback}>
            <c-grand-child contact-id={contactData.recId}></c-grand-child>
        </div>
    </div>
</template>

grandChild.js

import GET_DATA from '@salesforce/apex/ClassName.methodName';
import DELETE from '@salesforce/apex/ClassName.methodName1';
import refreshApex from '@salesforce/apex';
export default class GrandChild extends LightningElement {
      @api contactId;
      feedbackList = [];
      wiredResult;
      wire(GET_DATA, {contactId : '$contactId'})
      feedbacks(result){
          this.wiredResult = result;
          if(result.data){
              this.feedbackList = result.data;
          }
      }
      
      deleteFeedback(event){
          let feedbackId = event.target.getAttribute('data-id');
          DELETE({feebackId : this.feedbackId})
          .then(result=>{
              return refreshApex(this.wiredResult);
              this.dispatchEvent(new CustomEvent('feedback',bubbles:true,composed:true));
          })
      }
      
}

grandChild.html

<template>
    <div for:each={feedbackList} for:item="fdbck" key={fdbck.Id}>
        <p>Provider : fdbck.Name</p>
        <p>Comment : fdbck.Comment</p>
        <p data-id={fdbck.Id} onclick={deleteFeedback}>DELETE</p>
    </div>
</template>

the console log of lstMyData shows updated feedback count after refreshApex. However, the same is not reflected in it's child (parent component in our case).

3
  • Without seeing a sample of your code, we can't really help you. This should happen automatically if the data is wired up correctly.
    – sfdcfox
    Commented Oct 7, 2020 at 18:53
  • Reactive properties are also "wired" in the same sense. That's what I'm referring to here. All properties set from a parent component should be marked as @api and handled appropriately.
    – sfdcfox
    Commented Oct 7, 2020 at 19:27
  • @sfdcfox I have updated my question, please let me know if it makes sense now? Appreciate your help.
    – sfdcnoob
    Commented Oct 7, 2020 at 19:29

1 Answer 1

5

Your problem is in the parent component logic. The component only copies the data on initial render/connection, not afterwards. Change your controller to:

export default class Parent extends LightningElement {
    @api set objContactData(value) {
        this.myContactData = [...value];
    }
    get objContactData() {
        return this.myContactData;
    }
    myContactData;
    showFeeback = false;
    connectedCallBack(){
        this.myContactData = Object.assign({},this.objContactData);
    }
    showFeedbacks(event){
        this.showFeeback =  !this.showFeeback;
    }
}

This way, each time the grandparent changes the data, you'll get a fresh copy.

You must log in to answer this question.

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