Salesforce

Two Way Binding in Lightning Web Components

Two Way Binding in Lightning Web Components

If you are migrating from Angular.js to Lightning Web Components (LWC), one of the first questions you’ll have is about binding. How do I take bind a property from my JS into a form field and have changes in the form field update that property… i.e. how do I do two way binding in LWC?

Well the answer is… you don’t.

LWC is designed with a one way data binding approach. Initially this can feel frustrating, especially for people who have come to love the simplicity two way. Let’s review what two way binding is before looking at one way binding.

Two way binding

Two way binding allows a model to render data into a view and allows that view to update the data in model. This is mostly used in form fields, for example a text input renders a value from the model, and when the user types data into the field, it is automatically pushed back into the model. In Angular.js we do this with ng-model:

<input type="text" ng-model="model.name" />
angular.controller("ctrl", function($scope) {
    $scope.model = {
        name: "Matt"
    };
});

Whilst doing this is great, there are some downsides to two way binding. There’s a lot of complexity to support it behind the scenes, mostly from how to handle a chain of events that may be triggered from a change in the UI. This is one of the reasons that other frameworks like React, Knockout, and now Lighting Web Components, implemented one way binding.

One way binding

One way binding means that the model is rendered in the view, but in order to update the model if the view changes, you must fire an event and handle that event to update the code in your controller.

Let’s walk through an example to see how this works in Lightning Web Components.

import { LightningElement, track } from 'lwc';

export default class OneWayExample extends LightningElement {

    @track name = 'Matt';

}

This is our simple LWC class. It uses the @track decorator to tell the LWC framework that our name property is reactive – i.e. that LWC should re-render the component when it changes.

https://developer.salesforce.com/docs/component-library/documentation/lwc/js_props_private_reactive

See the Salesforce Developer Guide for more details about @track

In order to render this into our components HTML we use the {name} syntax:

<template>
   <input type="text" value={name} />
   <p>My name is {name}</p>
</template>

If we test out this code we’ll see the following:

Demo of our initial code showing that two binding isn't out of the box in LWC

https://developer.salesforce.com/docs/component-library/tools/playground

Another incredibly cool product that came out with LWC is the Playground where you can quickly test some simple components without deploying to an org.

It does… well nothing!

And that’s because we have only one way binding. So how do we get the changes to update the model? We need to add an event listener.

Event Listeners

This is one of my favourite things about LWC. Event Listeners are just standard DOM event listeners. There’s no custom syntax, or event object, it’s just pure Web Standards. That means that the docs you read on sites like MDN (for example https://developer.mozilla.org/en-US/docs/Web/Events/click) apply to LWC! The only difference is that you can attach an event handler using the binding syntax of onsomeevent={myEventHandler}. Let’s add an onkeyup handler to our example:

<template>
   <input type="text" value={name} onkeyup={updateName} />
   <p>My name is {name}</p>
</template>

In the HTML all we do is add our onkeyup listener and tell it what function on our class to call when it’s fired. The class looks like this:

import { LightningElement, track } from 'lwc';

export default class OneWayExample extends LightningElement {

    @track name = 'Matt';

    updateName(event) {
        this.name = event.target.value;
    }

}

Our updateName function get’s the target element (in this case the <input />) and then it’s current value and assigns it to our name property in the class. Let’s see this in action now:

Demo showing one way binding with event to update model.

And now we can see the value is automatically updating as we change the text in the field.

And that’s really all there is to it!

Where to go from here?

Obviously this is a very simple example and as you create more and more complex applications how you represent state will get more complicated too. So one concept from React that I’ve found helpful as more and more components get nested is called Lifting State Up. In a future post I’ll cover how this looks in the LWC world.

For further information check out the following links:

Author: Matt Goldspink

I'm a web developer based in the UK. I'm currently UI Architect at Vlocity, Inc, developing UI's on the Salesforce platform using a mix of Web Components, Angular.js and Lightning.

2 Comments on “Two Way Binding in Lightning Web Components

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.