[SalesForce] Track Input value in LWC

What

I'm trying to bind a controller variable with lightning-input's value. For instance myVar

So far

Following all examples and documentation of LWC I'm able to do so by using the onchange method and value attribute in this way.

lwc.html

<lightning-input type="number" name="input1" value={myVar} onchange={input1OnChange}></lightning-input> 

lwc.js

//... declaration lines
//...

@track myVar = 0;

input1OnChange(event){
   this.myVar = event.target.value;
}

This works fine in both directions of changes (From the input element or from the js controller). But it is tedious when you have several inputs.

What I was expecting

I was expecting that a @track notation on some controller variable gets updated the value automatically from the input element when it changes.

<lightning-input type="number" name="input1" value={myVal}></lightning-input> 

Question

Why is not LWC framework handling input element > controller variable change automatically?
In other words, why binding is not bidirectional? I don't think performance is the answer because the listener is the most costly part and is already implemented.

Update

Based on the feedback received here I found a more generic way to deal with a large number of bindings using this approach:

lwc.html

 <lightning-input name="input1" onchange={genericOnChange} value={input1}></lightning-input> 
    <lightning-input name="input2" onchange={genericOnChange} value={input2}></lightning-input> 

lwc.js

    @track input1 = 0;
    @track input2 = 0;

    genericOnChange(event){
        this[event.target.name] = event.target.value;
    }

Best Answer

You can use a single handler to capture the values in all of your inputs.

Here is my favorite approach that has 0 maintenance once you put it in, all you need to know is what "Field" and what "Value" and you can pump an object full of this information, just like a map with key and value.

Uncommented Solution:

@track theRecord = {};

handleFormInputChange(event){
    this.theRecord[event.target.name] = event.target.value;
}

<lightning-input type="time" name="FirstName" label="First Name"
                                        onchange={handleFormInputChange}
                                        class="formInput"></lightning-input>

This uses an object and bracket notation to assign the data to the correct object property.

I've used this many times to keep changes easy, adding fields to HTML and logic to JS without having to touch the handler.

Commented Solution:

// define your object, it'll look just like an sobject in the end
@track theRecord = {};

handleFormInputChange(event){
    // In 1 line, assign the value to the property
    this.theRecord[event.target.name] = event.target.value;
    console.log(event.target.name + ' now is set to ' + event.target.value);
}


// example: 
      // event.target.name == 'FirstName'
      // event.target.value == 'Mike'
      
      // End result: 
        // this.theRecord.FirstName = 'Mike';
        // Dynamically created a new property for theRecord... it'll look like this:
        // this.theRecord = {FirstName: 'Mike'};

    // see the full structure of our object as it grows
    // console.log('theRecord: ' + JSON.stringify(this.theRecord, null, '\t'));


html: 

<div>See output like {theRecord.FirstName} {theRecord.MiddleName} {theRecord.LastName}</div>

<lightning-input type="time" name="FirstName" label="First Name"
                                        onchange={handleFormInputChange}
                                        class="formInput"></lightning-input>

<lightning-input type="time" name="MiddleName" label="Middle Name"
                                        onchange={handleFormInputChange}
                                        class="formInput"></lightning-input>

<lightning-input type="time" name="LastName" label="Last Name"
                                        onchange={handleFormInputChange}
                                        class="formInput"></lightning-input>