Thursday 14 November 2019

Two way data binding in LWC

November 14, 2019 Posted by Sandeep 1 comment
One of the most commonly used feature when developing aura components was two way  data binding. All the fields displayed on a screen were related to a single JSON object and that JSON object was later used in a DML operation in an Apex class.



The code for above functionality is:

<aura:component >
    <aura:attribute name="myObject" type="Map" default="{}"/>
    <lightning:layout>
        <lightning:layoutItem size="6" padding="around-medium">
            <lightning:input name="textField" value="{!v.myObject.textField}" label="Text Field"/>
        </lightning:layoutItem>
        <lightning:layoutItem size="6" padding="around-medium">
            <lightning:input name="IntegerField" value="{!v.myObject.IntegerField}" type="number" label="Integer Field"/>
        </lightning:layoutItem>
    </lightning:layout>
    <div class="slds-p-around_medium">
        String  = {!v.myObject.textField}<br/>
        Integer = {!v.myObject.IntegerField}
    </div>
    
</aura:component>
The code does not require any Javascript logic and is quite handy in situations where data in fields had to be associated with a JSON object.

With LWC though, we have to manually bind fields to record changes in them. While this makes field binding logic more in line with other JS frameworks, for people who have been introduced to Javascript through Aura this change can be quite challenging.
A look into the LWC recipes library by salesforce, the example shown for data binding requires a developer to manually bind each and every field present on the UI using the change event handlers. While this would be manageable for a few fields.If there are a lot of fields on the UI that all are related to a JSON object. Writing checks for each and every field simply means a lot of redundant code and it is just not practical.

Enter data-* Attributes and dynamic JavaScript objects:
The data-* attributes are used to store custom data private to the page or application.
Have a look at this stack overflow thread in case you want to understand how dynamic objects are created in JavaScript. Using these two features we can build an object structure that is in line with Salesforce objects and can be directly sent to Apex for DML or any other operation that we wish to perform.

The LWC code replicating the above given functionality with minimal lines of code is:
<template>
    <lightning-card>
        <lightning-layout>
            <lightning-layout-item size="6" padding="around-medium">
                <lightning-input data-field="textField" label="Text Field" onchange={fieldChanged}></lightning-input>
            </lightning-layout-item>
            <lightning-layout-item size="6" padding="around-medium">
                <lightning-input data-field="IntegerField"  type="number" label="Integer Field" onchange={fieldChanged}></lightning-input>
            </lightning-layout-item>
        </lightning-layout>
        <div class="slds-p-around_medium">
            String  = {myObject.textField}<br/>
            Integer = {myObject.IntegerField}
        </div>
    </lightning-card>
</template>

If you will have a look at the lightning-input fields in the above code you will notice 2 things:
1. Both of them call the same on change event called fieldChanged
2. The data-field attribute should specify the key value for the JSON object(In case of Salesforce object we can name it as the field API name)
The Javascript logic for the web component is as follows:
import { LightningElement, track } from 'lwc';

export default class databinding extends LightningElement {
    @track myObject = {}
    fieldChanged(event){
        this.myObject[event.target.getAttribute('data-field')] = event.target.value;
    }
}
That's it! The one line written in the fieldChanged function will bind the fields with the myObject.
The above template can be leveraged to bind as many fields with a JSON object in Javascript.

The working example can be found here.


1 comment:

  1. Hi Sandeep,
    Great blog. It would also be helpful if you can also talk how json objects will be helpful to carry data across multiple components and an example to bind data to a salesforce object. Keep up the great work on your blog!!
    Buyan

    ReplyDelete