4

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;
    }
  • In your input you have myVal, in your controller you have myVar, or is it just a typo in your post? – glls May 5 at 18:18
  • typo fixed, good catch – Martin Borthiry May 5 at 18:33
1

In other words, why binding is not bidirectional?

LWC is designed with one way data bind in mind, therefore, it's now a required action on your part to retrieve anything (even out of a base component). Emphasis mine:

The data binding between components for property values is one-way.

To communicate up from a child component to a parent component, send an event.

Which is exactly what salesforce is doing, they are allowing access to a standard event which carries the payload of the value (event.target.value) for you to manually deal with.

  • Thank you for your answer @tsalb, That is exactly my understanding of how it works. But my questions WHY was designed in that way? In a component that involves more than 20 inputs is a mess to have 20 onChange identical handlers. That has no sense for me. – Martin Borthiry May 6 at 8:07
  • @Martin Borthiry that's a question to the LWC team, but IIRC it was due to having more predictable behavior. Two way data binding was a double edged sword and Salesforce must have thought it did more harm than good (across the ecosytem) – tsalb May 6 at 15:29
  • @MartinBorthiry actually, i was playing with attaching events dynamically today. In your specific use case, you would use this.template.querySelectorAll('.my-inputs') and iterate through the collection to dynamically .addEventListener to it. – tsalb May 7 at 0:15
  • Thank you James. That is a good approach indeed. You gave me a good insight. Please take a look at my updated post. – Martin Borthiry May 7 at 7:22
1

It is not there but you can avoid by defining 20 handlers.

Don't use multiple event handlers. Just create on the handler and call it on all 20 inputs. I am using this way:

    handleFormInputChange(event){
    if( event.target.name == 'tag_name_0' ){
        <Your Var> = event.target.value;
    }
    else if( event.target.name == 'tag_name_1' ){
        <Your Var> = event.target.value;
    }
    else if( event.target.name == 'tag_name_2' ){
        <Your Var>= event.target.checked;
    }
    else if( event.target.name == 'tag_name_3' ){
        <Your Var> = event.target.value;
    }
}

<lightning-input type="time" name="tag_name_0" label="Label 1"
                                        onchange={handleFormInputChange}
                                        class="formInput"></lightning-input>

<lightning-input type="time" name="tag_name_1" label="Label 2"
                                        onchange={handleFormInputChange}
                                        class="formInput"></lightning-input>

<lightning-input type="time" name="tag_name_2" label="Label 3"
                                        onchange={handleFormInputChange}
                                        class="formInput"></lightning-input>

<lightning-input type="time" name="tag_name_3" label="Label 4"
                                        onchange={handleFormInputChange}
                                        class="formInput"></lightning-input>
  • Thank you for your suggestion. It is true that a generic handler could be made – Martin Borthiry May 7 at 7:24

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.