3

With a simple component like so:

import { LightningElement, track, api } from 'lwc';

export default class App extends LightningElement {


    @track infoText;
    @track data = [];

    handleItemRemove(e) {
        this.infoText = e.detail.item.name
    } 

    handleClickW(e) {
        this.data.push({ label: 'a ' + this.data.length, name: 'b' + this.data.length })
        this.redraw = true;
        this.infoText = 'Count:' + this.data.length;
    }
}

HTML:

<template>
    <div class="slds-m-vertical_medium">
        <p>Info: <span class="slds-text-heading_small">{infoText}</span></p>
    </div>
    <div>
        <lightning-button label="Neutral" title="Neutral action" 
        onclick={handleClickW} class="slds-m-left_x-small"></lightning-button>
    </div>


     <lightning-pill-container items={data} onitemremove={handleItemRemove}>
    </lightning-pill-container>

</template>

I never see the items in my {data} displayed in lightning-pill-container. I can get the initial set of items displayed if i wrap lightning-pill-container into a if:true={redraw} and then set it to true on click, but setting it back to false and then to true did not work.

Link in playground: https://developer.salesforce.com/docs/component-library/tools/playground/v2VK0x6o_/1/edit

How can i add items to the list displayed by lightning-pill-container?

UPDATE

I sort of got it working like so:

@track redraw = false;
    handleClickW(e) {
        this.redraw = false;
        this.data.push({ label: 'a ' + this.data.length, name: 'b' + this.data.length })
        setTimeout(() => { this.redraw = true;}, 0);
        this.infoText = 'Count:' + this.data.length;
    }



<div if:true={redraw}>
     <lightning-pill-container items={data} onitemremove={handleItemRemove}>
    </lightning-pill-container>
    </div>

There are 2 issues: 1) Supposedly setTimeout is not allowed in lwc: Restricted async operation 'setTimeOut' in LWC 2) There is a jitter when i try to add items as the whole thing needs to be re-drawn.

1 Answer 1

3

Child components only rerender when its tracked values change. When passing data structures down to child components, we're actually passing by reference, so the reference to the data structure needs to change. In other words, the child component needs to receive a new data structure.

In LWC, data structure mutations can cause components to rerender, but only for the component that owns said data structure. In your example, lightning-pill-container does not update upon mutations to the this.data array because those mutations happen in the c-app component.

I made some modifications to your playground example to illustrate this better: https://developer.salesforce.com/docs/component-library/tools/playground/v2VK0x6o_/2/edit

On a related note, it's a best practice to clone your data structures before passing them around because you don't want other components to mutate your data.

1
  • it's a best practice to clone your data structures before passing them around because you don't want other components to mutate your data. would've thought that will eventually cause everything to be replicated over and over and over and your browser will run out of RAM. Many thanks for pointing me to the right solution!
    – zaitsman
    May 30, 2019 at 0:29

You must log in to answer this question.

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