5

I have the following need. I built a LWC to display a lightning-input for "field" object passed in from a parent LWC for a user to update.

@track field = { 'id' : 'some-id', 'value' : 'user value' };

I have built a simple getter and setter for my field var. I am able to initially set and get my field var. However, using an onchange handler, I am unable to update the field.value property for this object. I am using my value getter in my html file to view the value change on the fly but it does not appear to be doing that. The idea is that this will create an event and put the entire field into the event to pass back to the parent LWC. Does anybody know what is going on?

<!--html -->
<template>
<template if:true={field}>
    <lightning-card title={id}>
        <lightning-input type="text" label={id} value={value} onchange={handleValueChange}></lightning-input>
        <p>Value: {value}</p>
    </lightning-card>
</template>
//js
import { LightningElement, track, api } from 'lwc'; 
export default class FieldCmp extends LightningElement {
@track _field;

@api
get field() {
    return this._field;
}

set field(val) {
    this._field = val;
}

get id() {
    return this._field.id;
}

get value() {
    return this._field.value;
}

handleValueChange(evt) {
    this._field.value = evt.target.value;
}
}

2 Answers 2

4

The value comes from an @api value, so it is completely locked down. You need to copy the value into an unlocked object, which is the point of using a custom getter/setter:

set field(val) {
  this._field = {...val};
}

See the Spread syntax for how this works. Also, a Playground. Note that the parent must check the value of the component's field value, as the value it has in it's @track value won't be updated, since this is a copy.

1

You want to pass the value back to the parent and update an object there?

First, pass the value you have updated to the parent via a CustomEvent

FieldCmp.js

handleValueChange(evt) {
    this._field.value = evt.target.value;
    this.dispatchEvent(new CustomEvent('fieldchange', { detail: { fieldName: this._field.value }})
}

In the "parent" do the following

parent.html

<c-field onfieldchange={handleFieldChange} field={myObject.fieldValue}></f-field>

parent.js, I am using the 'spread" operator to mutate the myObject object in the parent with the updated value passed from the onChange event in the child

@track myObject = { 
  fieldValue: 'whatever'
}

handleFieldChange(event){
   this.myObject = { ...myObject,
   fieldValue: event.detail.fieldName }
}

You must log in to answer this question.

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