0

I'm making a component that renders filters based on any sObjects, to render records based on those filters. The component renders, depending on the type of the filter (boolean, number, with options) a different type of lightning component (input, combobox, custom multi select). The parent controller receives, via apex, the filters. Those filters are passed to a child component that iterates over them, and for each one, renders another child component which has the logic for what to render. Here is the code of the last child component:

import { LightningElement, api } from 'lwc';
export default class LwcFilter extends LightningElement {
@api filter;

get isBoolean(){
    return this.filter.type === 'boolean';
}

get isInput(){
    return this.filter.type === 'string' || this.filter.type === 'number';
}

get isSelect(){
    return this.filter.type === 'options';
}

get isMultiSelect(){
    return this.filter.type === 'options-multiple';
}

get isComposable(){
    return this.filter.type === 'composable';
}

get composableSelectFilter(){
    if(this.filter.type === 'composable'){
        return this.filter.filters[0];
    }
}

get composableSecondFilter(){
    if(this.filter.type === 'composable'){
        return this.filter.filters[1];
    }
}

handleOnChange(event){
    const selected = event.detail.value;
    this.filter.value = selected;
}

getValue(event){
    const selected = event.target.value;
    this.filter.value = selected;
}

}

Html:

<template>
<template if:true={filter}>
    <div>
        <lightning-input
            if:true={isInput}
            type={filter.type}
            label={filter.label}
            onchange={getValue}>
        </lightning-input>
        <lightning-input
            if:true={isBoolean}
            type={filter.type}
            label={filter.label}
            onchange={getValue}>
        </lightning-input>
        <lightning-combobox
            if:true={isSelect}
            label={filter.label}
            options={filter.options}
            onchange={handleOnChange}>
        </lightning-combobox>
        <c-multi-select
            onchange={handleOnChange}
            if:true={isMultiSelect}
            label={filter.label}
            options={filter.options}>
        </c-multi-select>
        <template if:true={isComposable}>
            <lightning-combobox
                options={composableSelectFilter.options}
                label={composableSecondFilter.label}>
            </lightning-combobox>
            <c-lwc-filter
                filter={composableSecondFilter}>
            </c-lwc-filter>
        </template>
    </div>
</template>
<!-- <template if:false={filter}>
    <p>error</p>
</template> -->

In the playground, the filters render correctly, but when I type anything in any of the inputs, salesforce throws an error, and in the 'technical stuff' section, it says 'script error' in the lightning input js. What could it be? Is it something on my code?

PD: how do I choose between the event.detail or event.target in the onchange handlers?

6
  • Are you sure in case of composable filter, these values are not undefined: composableSelectFilter and composableSecondFilter I think that is where the issue is. Check if there are values in the filters array. Dec 10 '20 at 12:39
  • Hey, how are you? Thanks for replying. No, I checked the console and I'm receiving the composable filters with its properties and values correctly. Dec 10 '20 at 12:44
  • 2
    Standard events, like onchange, don't have an event.detail. You use them like normal events. Custom events (may) have an event.detail, which is whatever payload the custom event is given during construction. I don't see any immediately obvious problems, but you can easily debug this by using Chrome's Developer Console area (F12). Open Developer Console, click on Sources, then click on the ⚙ icon and check "Break on caught exceptions." Generate the exception, and you should see where it broke and why. This can help diagnose the problem.
    – sfdcfox
    Dec 10 '20 at 12:49
  • Oh, ok, thanks! So, in this case I just want to retrieve what the user inputs, and save it in the value of the filter. I just use event.target for every type of component? (number and string inputs, combobox, etc). Dec 10 '20 at 12:51
  • 1
    I think it is because of cached objects are read only, and I'm trying to modify the value of the filter that is cacheable. Dec 10 '20 at 13:00
2

Someone helped me by telling me to create a setter and use rest parameters to make a mutable copy of the filter received by the parent component, this solved it:

_filter; @api set filter(value) { this._filter = {...value}; } get filter(value) { return this._filter; }

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.