0

I have a template tag with if:true attribute at the top level of my html file. When the page first renders, the content can be displayed normally. However, after clicking the refresh button I would like to hide the content by changing the ready variable to false, but the whole component is still rendered in spite of that.

Here is the html template:

<template>
<template if:true={ready}>
    <lightning-layout>
        <lightning-layout-item padding="around-small">
            <lightning-button variant="brand" label="Refresh" onclick={handleRefreshView}></lightning-button>
        </lightning-layout-item>
    </lightning-layout>
    <br/>
    <template for:each={reportItems} for:item="contractType" for:index="i">
        <table key={contractType.contractName} class="slds-table slds-table_cell-buffer slds-table_bordered slds-table_col-bordered slds-table_striped slds-no-row-hover">
            <thead align="center">
                <tr class="slds-line-height_reset">
                    <th>NPV Analysis ({contractType.contractLabel})</th>
                    <template for:each={contractType.products} for:item="item" for:index="index">
                        <th key={item.productName} colspan="5">{item.productName}</th>
                    </template>
                    <th rowspan="2">Total</th>
                </tr>
                <tr class="slds-line-height_reset">
                    <th></th>
                    <template for:each={contractType.products} for:item="item">
                        <th key={item.productName}>Year 0</th>
                        <th key={item.productName}>Year 1</th>
                        <th key={item.productName}>Year 2</th>
                        <th key={item.productName}>Year 3</th>
                        <th key={item.productName}>Total</th>
                    </template>
                </tr>
            </thead>
            <tbody>
               //... table content
            </tbody>
        </table>
    </template>
</template>
</template>

Controller:

import { LightningElement, track, api, wire } from 'lwc';
import retrievePricingItemsNPV from '@salesforce/apex/HGC_BCS01_BCaseController.retrievePricingItemsNPV';

export default class BCaseNPV extends LightningElement {

    @api bCaseId;
    @track ready = false;
    wiredPricingItemsResult;

    @wire(retrievePricingItemsNPV, { bCaseId: '$bCaseId'})
    handlePricingReport(result) {
        this.wiredPricingItemsResult = result;
        if(result.data) {
            this.reportItems = result.data;
            this.ready = true; // Template can be rendered
        } else if(result.error) {
            console.error(result.error);
        }
    }

    handleRefreshView() {
        this.ready = false; // Template is not hidden
    }

}

I suspect that having nested for:each tag might have something to do with it. Also some for:each tags have multiple children which is not assigned a unique key yet, I'm not sure if this is related to the issue.

Any advice would be appreciated!

  • 1
    Have you tried a console.log inside handleRefreshView to see if it is really invoked by the button? – Sander de Jong Apr 9 at 9:30
  • It is also possible that the data and window refresh are done in one and the same event. That at the first opportunity for the window to refresh, the data has already been fetched and ready is true again. – Sander de Jong Apr 9 at 10:00
  • @SanderdeJong That's exactly it; the wire method would be called again (using cached data), so it immediately flips back to true. – sfdcfox Apr 9 at 15:24
  • @sfdcfox I have put a breakpoint inside the wire method and I can confirm that the wire method is not called at any point after the page renders. – gbw939 Apr 14 at 3:06
1

There are two things i don't see here. 1. this.reportItems is not in your sample 2. You are always setting it to true, versus setting to false if you have no report items.

I have made a small modification to the code here to handle setting the value to false based on the reportItems from your wire method, and added the reportItems variable in here.

import { LightningElement, track, api, wire } from 'lwc';
import retrievePricingItemsNPV from '@salesforce/apex/HGC_BCS01_BCaseController.retrievePricingItemsNPV';

export default class BCaseNPV extends LightningElement {

    @api bCaseId;
    @track reportItems = [];
    @track ready = false;
    wiredPricingItemsResult;

    @wire(retrievePricingItemsNPV, { bCaseId: '$bCaseId'})
    handlePricingReport({ error, result }) {
        this.wiredPricingItemsResult = result;
        if(result ) {
            this.reportItems = result.data ?  [ ...result.data ] : [];
            this.ready = this.reportItems && Array.isArray( this.reportItems ) && this.reportItems.length > 0;
        } else if(result.error) {
            console.error(result.error);
            this.ready = false;
        }
    }

    handleRefreshView() {
        this.ready = false; // Template is not hidden
    }

}

Hope this helps get you on your way.

| improve this answer | |
-1

I have fixed this problem by adding another condition denoted by if:false={ready}.

Without the false condition the items are rendered regardless of the boolean flag, but once I add it then it works as expected!

The final template is as follows:

<template>
<template if:true={ready}>
    <lightning-layout>
        <lightning-layout-item padding="around-small">
            <lightning-button variant="brand" label="Refresh" onclick={handleRefreshView}></lightning-button>
        </lightning-layout-item>
    </lightning-layout>
    <br/>
    <template for:each={reportItems} for:item="contractType" for:index="i">
        <table key={contractType.contractName} class="slds-table slds-table_cell-buffer slds-table_bordered slds-table_col-bordered slds-table_striped slds-no-row-hover">
            <thead align="center">
                <tr class="slds-line-height_reset">
                    <th>NPV Analysis ({contractType.contractLabel})</th>
                    <template for:each={contractType.products} for:item="item" for:index="index">
                        <th key={item.productName} colspan="5">{item.productName}</th>
                    </template>
                    <th rowspan="2">Total</th>
                </tr>
                <tr class="slds-line-height_reset">
                    <th></th>
                    <template for:each={contractType.products} for:item="item">
                        <th key={item.productName}>Year 0</th>
                        <th key={item.productName}>Year 1</th>
                        <th key={item.productName}>Year 2</th>
                        <th key={item.productName}>Year 3</th>
                        <th key={item.productName}>Total</th>
                    </template>
                </tr>
            </thead>
            <tbody>
               //... table content
            </tbody>
        </table>
    </template>
</template>
<template if:false={ready}>
   <!-- Display if not ready -->
</template>
</template>
| improve this answer | |

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.