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.
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.
(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:
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 theevent
and takes theevent.target.value
and appends it to theinput_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:
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 + ' ' ;
};
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:
(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
.