3

I am trying to build a cart where I add products to it and can then remove them. However on remove I receive the error ['set' on proxy: trap returned falsish for property '0'].

In my component ParentComponent, I select the products and add to an array cartItems. For each cart item a child component called cartRowItem is instantiated. See code below:

parentComponent.html:

<template>
    <div class="slds-grid slds-gutters">
            <lightning-card class="slds-col slds-size_1-of-3" title="Product Search">
                <div class="slds-grid slds-gutters">
                    <div class="slds-col slds-size_2-of-3 slds-var-m-left_small">
                        <lightning-input type="text" placeholder="Search for a product" value={productSearchKey} onchange={handleSearchKeyChange}></lightning-input>
                    </div>
                    
                    <div class="slds-col slds-size_1-of-3">
                        <button class="slds-button slds-button_brand slds-button_stretch slds-var-m-right_small" onclick={doSearch}>Search</button>
                    </div>
                </div>

                <template if:true={products}>
                    <lightning-datatable
                        key-field="id"
                        data={products}
                        columns={columns}
                        onrowaction={addToCart}
                        hide-checkbox-column>
                    </lightning-datatable>
                </template>
                
            </lightning-card>

        <lightning-card class="slds-col slds-size_2-of-3" title="Product Cart">
            <template for:each={cartItems} for:item="item">
                <c-cart-row-item key={item.id} cart-item={item} cart-items={cartItems} oncartitemremove={handleRemove}></c-cart-row-item>
            </template>
        </lightning-card>
    </div>
</template>

parentComponent.js:

import { LightningElement, api, track } from 'lwc';
import findProducts from '@salesforce/apex/TechDocSelfServeController.findProducts';

const tableColumns = [{
    label: 'Product Code',
    fieldName: 'ProductCode',
    type: 'text',
    sortable: true
},
{
    label: 'Product Name',
    fieldName: 'Name',
    type: 'text',
    sortable: 'true'
},
{
    label: 'Add to Cart',
    type: 'button-icon',
    
    typeAttributes: 
    {
        iconName: 'utility:add',
        name: 'addToCart',
        title: 'addToCart',
        disabled: false,
        alternativeText: 'Add to Cart',
    }
}];

export default class TechDocSelfServe extends LightningElement {
    products; 
    @api cartItems = [];
    columns = tableColumns;
    productSearchKey = '';
    error;
    
    doSearch() {
        let productSearchKey = this.productSearchKey;
        findProducts({ productSearchKey })
            .then((result) => {
                this.products = result;
                this.error = undefined;
            })
            .catch((error) => {
                this.error = error;
                this.products = undefined;
            });
    }

    addToCart(event) {
        const row = event.detail.row;
        this.cartItems = [...this.cartItems, row];
    
        const selectedEvent = new CustomEvent("cartitemadd", {
            detail: this.cartItems
        });

        console.log('cartItems on add -> ' + JSON.stringify(this.cartItems, null, 4));

        this.dispatchEvent(selectedEvent);
    }

    handleSearchKeyChange(event) {
        this.productSearchKey = event.target.value;
    }

    handleRemove(event) {
        this.cartItems = event.detail
    }
}

cartRowItem.html:

<template>
    <template if:true={displayRow}>
        <div class="slds-var-m-around_xx-small slds-box">
            <lightning-card>
                <div class="slds-text-heading_large slds-text-align_center "><u>{cartItem.Name}</u></div>
                    <lightning-button variant="destructive" label="Remove Item" title="RemoveItem" onclick={handleRemove} value={cartItem} class="slds-align_absolute-center"></lightning-button>
            </lightning-card>    
        </div>
    </template>
</template>

cartRowItem.js (updated as per Rahul comment):

import { LightningElement, api } from 'lwc';

export default class CartRowItem extends LightningElement {
    @api cartItem;
    _cartItems;
    displayRow = true;

    @api get cartItems() {
        return this._cartItems;
    }

    set cartItems(value) {
        this._cartItems = value;
    }

    handleRemove(event) {
        console.log('Should remove here.')
        var array = this._cartItems;
        var key = event.target.value.Id;
        var index = array.findIndex(function(item, i) {
            return item.Id === key
        });

        array.splice(index, 1);
        this._cartItems = array;

        console.log('cartItems after remove -> ' + JSON.stringify(this._cartItems, null, 4));
        
        const selectedEvent = new CustomEvent("cartitemremove", {
            detail: this._cartItems
        });

        this.dispatchEvent(selectedEvent);
        this.displayRow = false;
    }
}

When pressing Remove button in cartRowItem I will receive the error ['set' on proxy: trap returned falsish for property '0'] with the number at the end changing depending on what item in the array I am trying to remove.

1 Answer 1

4

The property set by the parent component is immutable, which mean's you can't modify that. You need to use the getter setter for the public property.

_cartItems;
...

@api
get cartItems(){
    return this._cartItems;
}

set cartItems(value){
    this._cartItems = JSON.parse(JSON.stringify(value));
}

Note that I have created new private property with different name i.e. _cartItems.

Now you can perform all the operations and update the _cartItems. To send updated data into parent, you need to dispatch a custom event from child.

6
  • 1
    @LukeBray please update your code in the question. Aug 18, 2020 at 14:44
  • thanks Rahul, have updated question.
    – Luke Bray
    Aug 18, 2020 at 15:02
  • @LukeBray are you still getting the same issue? or this is something else now? Aug 18, 2020 at 15:05
  • It's the same issue
    – Luke Bray
    Aug 18, 2020 at 15:07
  • 1
    Thank you @RahulGawale, this worked.
    – Luke Bray
    Aug 18, 2020 at 16:07

You must log in to answer this question.

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