0

When changing picklist values in my LWC, an array is populated/updated via apex. I assign the updated information to an array but the component does not rerender and therefore does not call a child component to update the page. It only calls the child component on the initial load.

PARENT HTML

<lightning-accordion class="accordian" allow-multiple-sections-open
    active-section-name={activeSections}>
    <lightning-accordion-section name="Option1" label="Option1">
        <c-child products={arr1}
        </c-child>
    </lightning-accordion-section>
</lightning-accordion>

PARENT JS

@track arr1 = [];
opportunityId;
@track opportunity = {};

connectedCallback() {
    this.productSelection();
}

handleBrandChange(event) {
    this.opportunity.Brand__c = event.detail.value;
    this.productSelection(); // call apex to update values (HTML Ommited)
}

productSelection() {
    Promise.all([
        getProductSelection({
            opportunityId: this.opportunityId,
            brand: this.opportunity.Brand__c 
        }),
    ])
        .then(result => {
            //set values ... 
            this.initializeProducts(result);

        })
        .catch(error => {
            //error handling ...
        })
}

initializeProducts(allProducts) {
    window.console.log('BEFORE this.arr1: ', JSON.parse(JSON.stringify(this.arr1)));

    //updated array information from apex method
    let tempArr1 = [];
    for (let i = 0; i < allProducts.length; i++) {
        if (allProducts[i].Product.Brand__c === 'Option1') {
            tempArr1.push(allProducts[i]);
        }
    }

    this.arr1 = tempArr1;
    window.console.log('AFTER this.arr1: ', JSON.parse(JSON.stringify(this.arr1)));

}

CHILD HTML (Snippit)

<template for:each={researchProducts} for:item="product">
    <tr key={product.Product.Id} class="slds-hint-parent">
        <td data-label="Existing" role="gridcell">
            <lightning-input type="checkbox" checked={product.Existing} disabled>
            </lightning-input>
        </td>
        <td data-label="New/Renewal" role="gridcell">
            <lightning-input data-id={product.Id} type="checkbox" checked={product.NewRenewal} onchange={handleProductSelected}>
            </lightning-input>
        </td>
        <td data-label="Research Products">
            <div class="slds-truncate" title={product.Product.Name}>{product.Product.Name} ({product.Product.ProductCode})</div>
        </td>
    </tr>
    </template>

CHILD JS

@api products;
@track researchProducts = [];
@api type
setupopp;
paymentopp;

connectedCallback() {
    window.console.log('CHILD PRODUCTS: ', JSON.parse(JSON.stringify(this.products)));
    this.paymentopp = this.type.includes('Payment');
    this.setupopp = this.type.includes('Setup');
    for (let i = 0; i < this.products.length; i++) {
        if (this.products[i].Product.Classification__c === 'Research' && this.products[i].Product.Family === 'Yearly Subscription') {
            this.researchProducts.push(this.products[i]);
        }
    }
}

The apex updates a boolean value as seen in the screenshots. You can see that when selecting a picklist value, the "NewRenewal" is true. After updating the arr1 property, it is now false. However the child console statement is never reached and the component is not rerendered to show the latest information from Apex.

I am confused since I am updating a boolean value within an object, within an array, which @track should detect the change and rerender my component.

On Initial Load:

enter image description here

After selecting a picklist value: (Notice no child console.log was produced)

enter image description here

6
  • Providing code for the child <c-child/> LWC would probably help debug this issue. It looks like the values are updated fine in the parent, but the child isnt refreshing the values properly.
    – lu_ke____
    Mar 10 at 0:36
  • @lu_ke____ added child component. I'm not sure since it doesn't even get to the connected callback of the child. Which makes me think its on the parent?
    – some guy
    Mar 10 at 0:48
  • Your child LWC markup will need to be wrapped on blank <template></template> tags. You also don't need to add window before your console.log() methods. Also missing a closing tag in your parent markup on the <c-child></c-child> component.
    – lu_ke____
    Mar 10 at 0:53
  • Thanks. The HTML is just a snippet since its actually quite large. I just added the relevant part. Hope thats okay. Happy to add the entire html if needed
    – some guy
    Mar 10 at 0:56
  • no problem, just checking that isn't the issue. Might be worth adding an if:true={arr1} to the <c-child/> on the parent. Is the connectedCallback on the child at least running the console log?
    – lu_ke____
    Mar 10 at 0:58

1 Answer 1

1

connectedCallback is only called when the component initially is attached to the DOM. Since this method is doing stuff to transform the list, then placing it in researchProducts, it will never be recalculated. Consider using a getter here:

get researchProducts() {
  this.paymentopp = this.type?.includes('Payment');
  this.setupopp = this.type?.includes('Setup');
  return !this.products 
    ? []
    : this.products.filter(
      (product) => product.Product.Classification__c === 'Research' &&
                   product.Family === 'Yearly Subscription'
      );
}

You can also try doing this in a setter, but be aware that not all data may be present on the first load, as properties are not guaranteed to be set in any particular order.

You might also want to consider using a setter for type as well.

_type
@api set type(value) {
  this.paymentopp = value?.includes('Payment');
  this.setupopp = value?.includes('Setup');
  this._type = value;
}
get type() {
  return _type;
}
_products;
@api set products(value) {
  this.researchProducts = (value || []).filter(
  (product) => product.Product.Classification__c === 'Research' &&
               product.Family === 'Yearly Subscription'
  );
  this._products = value;
}
get products() {
  return this._products;
}
0

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.