1

Main LWC HTML:

<template>
    <c-product-code-entry onproductidchanged={passProductIdToDisplayPanel}></c-product-code-entry>
    <c-stock-display-panel></c-stock-display-panel>
</template>

Main LWC JS:

import { LightningElement } from 'lwc';

export default class ProductStockDisplay extends LightningElement
{
    passProductIdToDisplayPanel(event)
    {
        //call the method in the child display panel to fetch the record details
        var inputProductCode = event.detail.prodId;
        console.log('inputProductCode Received');
        console.log(inputProductCode);
        this.template.querySelector('c-stock-display-panel').fetchProductDetails(inputProductCode);
    }
}

Event Firing Child LWC html:

<template>
    <lightning-card title="Enter Product Code below">
        <lightning-input label="Product Code" class="inputProductCode"></lightning-input>
        <br/>
        <lightning-button variant="brand" label="Fetch Product Details" title="Product Details" onclick={passProductCodeToParent} class="slds-m-left_x-small"></lightning-button>
    </lightning-card>
</template>

Event firing Child LWC JS:

import { LightningElement,track } from 'lwc';

export default class ProductCodeEntry extends LightningElement
{
    passProductCodeToParent(event)
    {
      var inputProductCode = this.template.querySelector('.inputProductCode').value
      console.log('inputProductCode');
      console.log(inputProductCode);
      const productIdChanged = new CustomEvent('productidchanged',{detail:{prodId:inputProductCode}});
      this.dispatchEvent(productIdChanged);
    }
}

Second Child HTML:

<template>
    <div class="mainDisplayPanel">
        <lightning-card footer="Remaining Stock Display" title="Remaining stock display">
            <template if:true={itemStatus.itemInStock}>
                <!--<lightning-badge label="Product Name"></lightning-badge>-->
                Item is in stock.
            </template>
            <template if:true={itemStatus.itemNotInStock}>
                Item is out of stock.
            </template>
        </lightning-card>
    </div>
</template>

Second Child JS:

import { api, LightningElement } from 'lwc';

export default class StockDisplayPanel extends LightningElement
{
    @api itemStatus = {itemInStock : false,itemNotInStock : false};
    @api
    fetchProductDetails(inpProdCode)
    {
        console.log('In Peer Panel finally :: ');
        console.log(inpProdCode);
        if(inpProdCode == 'CN60K' || inpProdCode == 'CN30K')
        {
            try
            {
            console.log('Stock block');
            console.log('itemStatus Before');
            console.log(itemStatus);
            this.itemStatus.itemInStock = true;
            this.itemStatus.itemNotInStock = false;
            console.log('itemStatus After');
            console.log(itemStatus);
            }
            catch(err)
            {
                console.log('err');
                console.log(err);
            }
        }
        else
        {
            console.log('No Stock block');
            this.itemStatus.itemInStock = false;
            this.itemStatus.itemNotInStock = true;
        }
    }
}
0

1 Answer 1

2
this.itemStatus.itemInStock = true;
this.itemStatus.itemNotInStock = false;

You can't do this. Marking an object as @api means that you expect it to only be set by the parent, and you should not presume that you can make any changes to it.

In addition, I'd like to note that your component can't respond to changes to the internal state of the variable, because it must be set by the parent directly in order to trigger new render cycle.

Since you're not using it externally, I'd suggest dropping @api:

itemStatus = {itemInStock: false, itemNotInStock: false};

This gives you the freedom to modify the object as you desire.

Note that, because of how you're using the object, you must also @track it in order to trigger render cycles when the status changes:

@track itemStatus = {itemInStock: false, itemNotInStock: false};

As a side note, this is kind of an unusual way to write this; I'd rather have a flag for one or the other for internal consistency:

@track itemStatus = {itemInStock: false};

And your template can still react to this:

<template if:true={itemStatus.itemInStock}>
    <!--<lightning-badge label="Product Name"></lightning-badge>-->
    Item is in stock.
</template>
<template if:false={itemStatus.itemInStock}>
    Item is out of stock.
</template>

This reads a bit easier in my mind. Finally, given all this trouble, why not just make the flag a simple Boolean variable?

 itemInStock = false;

And in your markup:

<template if:true={itemInStock}>
    <!--<lightning-badge label="Product Name"></lightning-badge>-->
    Item is in stock.
</template>
<template if:false={itemInStock}>
    Item is out of stock.
</template>

As a bonus, you no longer need to @track your variable.

Also, I noticed you forgot some this references. You need to reference class variables with this, or you'll be referencing a local variable.

console.log(itemStatus); // undefined
console.log(this.itemStatus); // { itemInStock: true, itemNotInStock: false }

Final Version:

import { api, LightningElement } from 'lwc';

export default class StockDisplayPanel extends LightningElement
{
    itemInStock = false;
    @api
    fetchProductDetails(inpProdCode)
    {
        console.log('In Peer Panel finally :: ');
        console.log(inpProdCode);
        if(inpProdCode == 'CN60K' || inpProdCode == 'CN30K')
        {
            try
            {
            console.log('Stock block');
            console.log('itemStatus Before');
            console.log(this.itemInStock);
            this.itemInStock = true;
            console.log('itemStatus After');
            console.log(this.itemInStock);
            }
            catch(err)
            {
                console.log('err');
                console.log(err);
            }
        }
        else
        {
            console.log('No Stock block');
            this.itemInStock = false;
        }
    }
}

....

<template>
    <div class="mainDisplayPanel">
        <lightning-card footer="Remaining Stock Display" title="Remaining stock display">
            <template if:true={itemInStock}>
                <!--<lightning-badge label="Product Name"></lightning-badge>-->
                Item is in stock.
            </template>
            <template if:false={itemInStock}>
                Item is out of stock.
            </template>
        </lightning-card>
    </div>
</template>

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.