Red Green Repeat Adventures of a Spec Driven Junkie

Learning Angular - Data Binding

I am continuing my journey in Learning Angular, this article will cover how to get data out and into component classes. I will demonstrate getting data out by using string interpolation and data in by using data binding on the input $event on a fresh Angular application. I will show how to get Angular’s two-way binding setup as well.

At the end of this article, my goal is that you will understand how to get data out and data in to components, the start of feedback in building a web application.

This article will take about seven minutes to read.

The Cloisters Cross source and more information

Introduction

When I start programming, I like to get data out and data in to functions I can work with. So far, in Angular, the simplest place to do this is in a component’s function. With a newly generated application, the AppComponent.

Once data can get out and in to your functions, that’s when your work can begin.

If you want to follow along, I am working from a fresh Angular 8 application by running:

$ ng new learning-angular-data-binding

Github repository

If you want to follow along with the code, the final form is available at Github:

https://github.com/a-leung/learning-angular/commit/60f6b2920c8edf77f3f865772f40c342d7f045f3

StackBlitz

I recently discovered StackBlitz, a whole web application development system in your browser, code editing and live previews. You can try out my code without installing anything.

StackBlitz link

(This works best in Chrome, I couldn’t get it to work in Chrome-based browsers, like Brave. :-/)

Pretty sweet!

AppComponent

The app.component.ts file defines the AppComponent class. The file’s contents are:

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
    title = 'learning-angular-data-binding';
}

What is the title variable and why is it set to the application’s name: learning-angular-data-binding??

Well, it looks like the template, app.component.html uses this value:

<!-- snipped - angular 8's start page has a lot more! -->
    <span>{\{ title }\} app is running!</span>
<!-- snipped rest -->

Right off the bat, a newly generated Angular app is getting data out of a function and into the template.

Sweet. That’s half our job right there.

Better solution

This is great if you want to make an app that only displays a static string (this would be more effective!)

<span>learning-angular-data-binding app is running!</span>

(no bugs, no framework needed! :-))

Question: how to get values out of the AppComponent class and how to get values into the AppComponent class to do real work?

Getting Values Out

The generated app provides a example of how to get values out of the app. To display any variable in the class, like title, use string interpolation, that means putting {{}} around the variable’s name, Handlebar syntax.

In the generated app example. the variable’s name is: title.

To have a more sophisticated example, I’ve changed the app.component.html content to match the section below:

hello world!
<br>
Today's date (in your timezone!) is: <br>
{\{ today_date }\}
<br>

In AppComponent section of the app.component.ts file, I’ve changed the function from:

export class AppComponent {
    title = 'learning-angular-data-binding';
}

to:

export class AppComponent {
  today_date = new Date();
}

Just taking a small step up from before.

When loading the page, the contents becomes:

Data Binding - String Interpolation

Thu Dec 26 2019 21:15:43 GMT-0500 (Eastern Standard Time) is not “static” text!

Using {{}} on any variable from the component is how to get data out of the component’s class!

Getting Input

To obtain user input from a form field into the AppComponent class, let’s add the following form details to the app.component.html file:

hello world!
<br>
Today's date (in your timezone!) is: <br>
{\{ today_date }\}
<br>
<br>
When you type a character into the box, the value of the form will be displayed below
<br>
<input (keyup)="onKey($event)"><br>
Value entered: <p>{\{input_value}\}</p>

The input is a regular text form and setting on every keyup event, call: onKey($event) function. source.

The `` is the class variable that will hold the value coming from the keyup event. I find this is the easiest way to show something is going in to the component, by having the component show what’s inside itself.

Let’s make the changes in the AppComponent class to support the template changes.

Class changes

To change the AppComponent class to support the template, change the AppComponent to the following:

export class AppComponent {
    today_date = new Date();  // the current date -> page
    input_value = ''; // set by user input (onKey event); page -> onKey -> page
    onKey(event: any) {
        this.input_value += event.target.value + '   ' ;
    };
}
  • input_value is the variable that stores the value from the input field.
  • onKey is a function that accepts the event and takes the event.target.value and appends it to the input_value with some spacing.

With the changes, restart the Angular server and open a browser.

Ta-Da~!

The following is what I saw and the interaction I had with the field:

Data Binding Input

Spiffy, right? If you ran into another issue, check out the console via the browser’s inspector. Contact me if it takes you more than ten minutes to figure out the problem.

Matching

Notice that the onKey function purposely combines the previous values:

    onKey(event: any) {
        this.input_value += event.target.value + '   ' ;
    };

This makes the demo obvious there’s more happening here than just “copying” things.

Changing the onKey function to will make the output match the field:

    onKey(event: any) {
        this.input_value = event.target.value; // += event.target.value + '   ' ;
    };

Data Binding - Own two-way

This is how you can roll your own two-way data binding in Angular.

Two Way Data Binding

Previously, a simple way to make your own two-way data binding is to change the onKey function to reflect the contents of the input form.

This can work if you want the event to be on keyup, notice that when holding the delete key down, the output is only updated when releasing the key.

One way to fix that is to use the keydown event. Another way: use Angular’s built-in two-way data binding!

Angular has a built-in two-way data binding that doesn’t need a lot of set up (or covering edge cases):

Modify app.component.html contents to match the following:

hello world!
<br>
Today's date (in your timezone!) is: <br>
{\{ today_date }\}
<br>
<br>
When you type a character into the box, the value of the form will be displayed below
<br>
<input (keyup)="onKey($event)"><br>
Value entered: <p>{\{input_value}\}</p>
<br>
Two-way data-binding<br>
<input [(ngModel)]="two_way_value"><br>
<br>
<br>
{\{ two_way_value }\}

Adding:

<input [(ngModel)]="two_way_value"><br>

This configures input to store the field value into variable: two_way_value

{\{ two_way_value }\}

Displays the value of two_way_value (I am taking the same approach as input_value.

AppComponent changes

Change app.component.ts contents to have just one more value: two_way_value, the contents of the AppComponent function will be:

export class AppComponent {
    today_date = new Date();  // the current date -> page
    input_value = ''; // set by user input (onKey event); page -> onKey -> page
    onKey(event: any) {
        this.input_value += event.target.value + '   ' ;
    };

    two_way_value; // by Angular using: FormsModule
}

Yes, the only change is adding: two_way_value.

app.module.ts changes

To use the built-in Angular two-way binding function and setup input to support [(ngModel)], the FormsModule needs to be bundled together with the AppComponent.

The only changes to the app.module.ts file are:

diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index f657163..8259825 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -1,5 +1,6 @@
 import { BrowserModule } from '@angular/platform-browser';
 import { NgModule } from '@angular/core';
+import { FormsModule } from '@angular/forms';

 import { AppComponent } from './app.component';

@@ -8,7 +9,8 @@ import { AppComponent } from './app.component';
     AppComponent
   ],
   imports: [
-    BrowserModule
+      BrowserModule,
+      FormsModule
   ],
   providers: [],
   bootstrap: [AppComponent]

Result

With the previous set of changes to the template, class, and module, restart the Angular server (if it’s not running already).

This is the result I had when interacting:

Data Binding - Angular two-way

(If you can’t get things going within 10 minutes, feel free to contact me.

Using Angular’s two-way binding is a bit nicer as there was only an additional of the variable in the class and setting up the template to use it.

If you notice, the reaction of the output is better as the input changes (i.e. when deleting each character, the display changes as well, where the hand-crafted two-way data binding display changes on keyup events.)

Using the Angular two-way data binding instead of a custom version means there’s less code to test as it is code I’m expecting to be thoroughly tested and optimized.

Conclusion

Getting data out and into a component’s class in Angular requires using data binding. This is an important part of developing an application.

To get data out of the class, using {{}} syntax around a class’ variable name is sufficient.

To get data into the class, setting up the input to pass the $event to class and extracting out the desired value.

If you want to get fancy and have two-way data binding, you can roll your own by immediately displaying input values back onto the page, or using Angular’s two-way data binding system from the FormsModule.