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
    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
    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
    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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.