Two-Way Data Binding (@track)
Two-way data binding in LWC will help users to exchange data from the controller to the template and form template to the controller. It will help users to establish communication bi-directionally.
note - Before Spring ’20, to make a field reactive, you had to decorate it with @track. You see this approach used in older code samples, and it’s still supported.
How to achieve Two-Way Data Binding?
- The Lightning Web Components programming model has given us some decorators that add functionality to property or function.
- @track is the decorator that helps us to track a private property's value and re-render a component when it changes.
- Tracked properties are also called private reactive properties.
@track
helps us to achieve two-way data binding
@track
is powerful, but remember, track a property only if you want the component to re-render when the property's value changes. Don't track every private property.
Example of Two-Way Data Binding
- In VS Code, open the Command Palette by pressing
Ctrl+Shift+P
on Windows orCmd+Shift+P
on macOS. - Type
SFDX
and SelectSFDX: Create Lightning Web Component.
- Type
twoWayDataBinding
as the name of the new component and pressEnter.
- Again, Press
Enter
to accept the defaultforce-app/main/default/lwc.
- Goto your
lwc
folder, you will see one new component with the nametwoWayDataBinding
gets created. - Let's add the following code to
twoWayDataBinding.html
,twoWayDataBinding.js
andtwoWayDataBinding.js-meta.xml
<template>
<lightning-card title="Two-way Data Binding Demo" icon-name="custom:custom2">
<hr />
<!--First input box-->
<div class="slds-p-around_medium">
<lightning-input
type="text"
name="fullname"
label="Enter your name:"
onkeyup={changeHandler}
value={fullname}
></lightning-input>
</div>
<!--Second input box-->
<div class="slds-p-around_medium">
<lightning-input
type="text"
name="title"
label="Enter your title:"
onkeyup={changeHandler}
value={title}
></lightning-input>
</div>
<!--Result of binding-->
<div class="slds-p-around_medium">
<h5>My name is {fullname} and my title is {title}</h5>
</div>
</lightning-card>
</template>
- we have created two input box
fullname
andtitle
usinglightning-input
inside thelightning-card
. {name}
- is used to bindfullname
property tofullname
input box{title}
- is used to bindtitle
property totitle
input box- we have defined an event handler called
onKeyUp
that is bind tochangeHandler
, which gets triggered on every key up. - We have used the
<h5>
tag to test the two-way data binding
import { LightningElement, track } from "lwc";
export default class TwoWayDataBinding extends LightningElement {
@track fullname = "Salesforce Troop";
@track title = "Salesforce developer";
changeHandler(event) {
this[event.target.name] = event.target.value;
}
}
- In the first line, we are importing
LightningElement
andtrack
fromlwc
module - After that, we are creating a
class
TwoWayDataBinding
(Note - the class name always be pascal case) - Within the
class
, we have to define two propertiesfullname
andtitle
. @track
decorator decorates both properties.- Both properties are assigned with an initial value of
Salesforce Troop
andSalesforce developer
, respectively. - We have defined a method
changeHandler
that takes the value from the textbox and update the property based on the input box name
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="twoWayDataBinding">
<apiVersion>46.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__AppPage</target>
<target>lightning__RecordPage</target>
<target>lightning__HomePage</target>
</targets>
</LightningComponentBundle>
dataBinding.js-meta.xml
is a configuration file- The configuration file defines the metadata values for the component, including the design configuration for Lightning App Builder and Experience Builder.
Final Output
After placing the component on the page, you will see the following output.
note - Before Spring ’20, to make the component rerender when a user entered a first or last name, you had to decorate the fields with @track.
Observe an Object’s Properties or an Array’s Elements
There is still one use case for @track. When a field contains an object or an array, there’s a limit to the depth of changes that are tracked. To tell the framework to observe changes to the properties of an object or to the elements of an array, decorate the field with @track.
Without using @track, the framework observes changes that assign a new value to a field. If the new value is not === to the previous value, the component rerenders.
To understand, let’s declare the fullName field, which contains an object with two properties, firstName and lastName.
fullName = { firstName : '', lastName : '' };
The framework observes changes that assign a new value to fullName. This code assigns a new value to the fullName field, so the component rerenders.
// Component rerenders.
this.fullName = { firstName : 'Mark', lastName : 'Doe' };
However, if we assign a new value to one of the object’s properties, the component doesn't rerender because the properties aren’t observed.
// Component doesn't rerender.
this.fullName.firstName = 'Mark';
The framework observes changes that assign a new value to the fullName field. This code doesn't do that, instead it assigns a new value to the firstName property of the fullName object.
To tell the framework to observe changes to the object's properties, decorate the fullName field with @track. Now if we change either property, the component rerenders.
// Component rerenders.
@track fullName = { firstName : '', lastName : '' };
this.fullName.firstName = 'Mark';