DEV Community

loading...
Cover image for Data Binding in Angular

Data Binding in Angular

Mark Dsouza
Taking control of my career & constantly learning to be a better Full Stack Developer.
・6 min read

In this article, let's take a look at what data binding in Angular really is and how we can use it. Once we get this figured out, let's see how this compares to doing something similar with HTML and JS

So what is Data binding?

Imagine the entire web page is split into different smaller individual parts - a header, a footer, maybe a sidebar, a main section(which probably has its own distinct sub-sections)- each with its own logic. These are called Components in Angular and it is basically the building block of Angular. Each Component defines a class that contains the application data and logic, and is associated with an HTML template that defines a view to be displayed in the target environment.
Data binding is all about how these 2 files can communicate with each other and how data flows between the Component(TypeScript controller source) and the View(HTML Template).

The Types of Data Binding

In general this can be split into
1) Data being passed from Component to View
2) Data being passed from View to Component
3) A Combination of the above two

1) Data is passed from the Component to the View

String Interpolation

If we want to display data which is in our component as text in our template. All we need to do is enclose it in {{ X }} . Where X would be the name of the variable/function returning the data to be displayed in the view.
Syntax : <div> {{valueFromComponent}} </div>
Note : You can even mention a function. The return value of the function will be assigned to the property
For Example: Say you are receiving some data from an API which has a JSON structure assigned to a variable let data = {header: 'Topic Header', details: 'all the details'}. Then you can use <h1>{{data.header}}</h1> <h5>{{data.details}}</h5> in your view to easily assign the data.
You do not need to get the independent elements using query selectors in JS and then assign it. I hope you see how powerful and easy it would be to map larger objects with basic string interpolation.

Property Binding

Next up is property binding where you can modify properties for DOM elements depending on values in the component.
Syntax : <div [propertyName] : "valueFromComponent"> </div>
We use square brackets [] to enclose the property we are trying to bind with the component file. You can even mention a function. The return value of the function will be assigned to the property.
A use case for this would be to have a button enabled only when a certain condition is met or assigning the src of an image to a Url that you receive from an API.
Example : <img [src]="imgSrcUrl"> where imgSrcUrl is present in the Component file.
We can use property binding to bind the class or even style
<div [class.sale]="onSale"></div> <div [style.background-color]="expression"></div>
Example of having logic in the expression -
<div [style.color]= "status=='Incomplete' ? 'red': 'green'"
[style.text-align]= "'center'" >

This allows us to have behavioral logic in the HTML file itself.
Note : Data binding works with properties of DOM elements, components, and directives, not HTML attributes.

2) Data is passed from the View to the Component

Event Binding

We can bind events to functions in our component Object. This is similar to adding event listeners in our JS file. Here we do that binding in the HTML itself
Syntax : <button (click)="methodInTSFile()"> Click </button>
This can be done for any events that the view may encounter
Example: <select (change) = "changeData($event)"> <option>1</option> <option>2</option> <option>3</option> </select>

3) Data is passed from the View to the Component and back

Two-Way binding

basically data flows both ways - from component to view and view to component. But what does this mean exactly? Say you have an input field where the user types in something. Once the input field value is changed, the variable it is associated with in the TS file also changes. If we update the field in the input file, it modifies the value displayed on the page as well. The user does not have to tag a change event to the element, it is automatically taken care of.
Syntax : <div [(ngModel)]="variableInTSFile"> Test </div>
This syntax is called 'Banana in a box'. If you look close, all it is is a combination of [] and (). Below might explain that a little better.
The below code, where myModel is a variable in the component object
<input [value]="myModel" (input)="myModel=$event.target.value" />
can be written in a single go as
<input [(ngModel)]="myModel">
combining property binding and event binding.
Note: ngModel is a directive that is part of the FormsModule. Please make sure you add it to your imports in the app.module.ts

Comparison with data-binding using vanilla JS

Below is the HTML & JS Code for the below business rules

  1. Page contains a heading, sub-heading, input field, checkbox, save button
  2. Heading, sub-heading and input field are populated by an API Call and are not known before hand
  3. On click of the checkbox, the save button should get toggled. By default on page load, save button should be disabled
  4. When the user clicks save, an API call is made with the data in the input field. the input field should be updated once the call is complete with the response.
  5. Ignore the API Call in the code. Write a comment wherever an API needs to be done. Now, lets take a peak at how you would implement the same logic in JS.

index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Data Binding</title>
</head>

<body>
    <h1 id="header"></h1>
    <h4>This is to show the <span id="subHeading"></span> demo</h4>
    <div class="container">
        <div>
            <input type="text" id="details">
            <br><br>
        </div>
        <div>
            <label for="isComplete">Completed?</label>
            <input type="checkbox" name="isComplete" id="isComplete">
            <br><br>
        </div>
        <div>
            <button id="saveBtn" disabled>Save</button>
        </div>
    </div>
    <script src="./script.js"></script>
</body>

</html>
Enter fullscreen mode Exit fullscreen mode

script.js

headerEl = document.getElementById('header');
subHeadingEl = document.getElementById('subHeading');
saveBtn = document.getElementById('saveBtn');
isComplete = document.getElementById('isComplete');
detailsEl = document.getElementById('details');

function setInitValues() {
  // get initial values after making an API Call
  let returnObj = { header: 'Data Binding', details: 'Enter details here...' };
  headerEl.innerText = returnObj.header;
  subHeadingEl.innerText = 'Data Binding';
  detailsEl.value = returnObj.details;
  console.log(`initialized page`);
}

function completeClicked(e) {
  //should call the toggle save button method
  console.log('clicked');
  toggleSaveBtn(e.target.checked);
}

function toggleSaveBtn(conditon) {
  //toggle save button depending on condition
  if (conditon) {
    saveBtn.disabled = false;
  } else saveBtn.disabled = true;
}

function saveDetails() {
  let details = detailsEl.value;
  console.log(`saved details :${details}`);
  //call api to save details which returns updated details
  detailsEl.value = 'Updated details...';
}

setInitValues();
isComplete.addEventListener('click', completeClicked);
saveBtn.addEventListener('click', saveDetails);

Enter fullscreen mode Exit fullscreen mode

Here we basically have to write query selectors to identify the elements we want to modify the value of or add event listeners to.

On Page Load
On Load

When checkbox is clicked
When Clicked

When Save is clicked
On Save

Now lets see how we can implement the exact same functionality with Angular. After creating my base angular project, below are the app component files

app.component.html

<h1 id="header">{{header}}</h1>
<h4>This is to show the {{subHeading}} demo</h4>
<div class="container">
  <div>
    <input type="text" id="details" [(ngModel)]="details">
    <br><br>
  </div>
  <div>
    <label for="isComplete">Completed?</label>
    <input type="checkbox" name="isComplete" id="isComplete" (click)='completeClicked($event)'>
    <br><br>
  </div>
  <div>
    <button id="saveBtn" [disabled]="disableSave" (click)=' saveDetails()'>Save</button>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

app.component.ts

import { Component } from "@angular/core";

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"],
})
export class AppComponent {
  title = "data-binding";
  header: string;
  subHeading: string;
  disableSave: boolean = true;
  details: string;

  ngOnInit() {
    // get initial values after making an API Call
    let returnObj = {
      header: "Data Binding",
      details: "Enter details here...",
    };
    this.header = returnObj.header;
    this.subHeading = "Data Binding";
    this.details = returnObj.details;
    console.log(`initialized page`);
  }

  completeClicked(e) {
    console.log("clicked");
    this.disableSave = !e.target.checked;
  }

  saveDetails() {
    console.log(`saved details :${this.details}`);
    //call api to save details which returns updated details
    this.details = "Updated details...";
  }
}

Enter fullscreen mode Exit fullscreen mode

On Load
Angular On  Load
On click of the checkbox
Angular On Click
On Save
Angular On Save

As you can see, in the above angular example, we have used string interpolation for setting the main heading and sub heading, used property binding to bind the disabled property of the save button. We use event binding for the checkbox click event and the save button click event. 2 Way binding is used for the details input field where the data is shared between HTML and TS file.

As the complexity of your page increases, the number of components you have also increase. Having a good data binding mechanism by using frameworks such as Angular, makes it a lot easier for the developer to write clean, error free code.

I hope you found this walkthrough useful and you are clear on everything related to data binding in Angular! Cheers ^_^

Discussion (0)