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.
Best Answer
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 thethis.data
array because those mutations happen in thec-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.