Microsoft and Apple Training
Data Binding
Agenda
The Importance of Binding
Templates
Component to View
– Types of Bindings
– Using Structural Directives
– Template Reference Variables
– Value Conversion
View To Component
– Handling Events
– Two-Way Data Binding
The need for Data Binding
A world without data binding
– Load data properties into the DOM
– Allow the user changes
– Synchronize your data objects with the DOM
– Casting from text to other types
DataBinding allows
– Using MV* pattern to separate View from data and logic
– Declarative synchronization between data and view
Model-View-ViewModel
Page
Presentation
+ Logic
+ Events
Page
Presen Data + Heavy use
tation Functions of databinding
Model
An object model that represents the real state content
Independent from presentation logic
– Easy to test
– Easy to re-use
In Angular, every property of a component is a model
View
Refers to all elements displayed by the Browser such as buttons, inputs,
selects, and other DOM Elements
Pure HTML
Relies heavily on data binding
– To data
– To functions
ViewModel
A ViewModel is an object that contains all of the data(models) and
functionality that a view binds to
In Angular, the component serves as a ViewModel for its Template
element
Command
Function
DOMData
Data
Data
Data
Data
Data
Data
Data
Data
View ViewModel Model
Templates
A template is a piece of HTML with 'markers'
These 'markers' are compiled by Angular
– We call them Directives
E.g. they can be used for Data Binding
One-way Binding
<div>
<p>Welcome {{user.username}}</p> Two-way Binding
<input [(ngModel)]="user.username" />
<input type="password" [(ngModel)]="user.password" />
<input type="button" (click)="login()" value="login" />
</div>
Bind to a function
Components can contain other components to create complex hierarchies
Templates
Templates can be specified in multiple ways:
– Using a URL to an HTML file
– Inline
To facilitate inline template you can use back ticks to write templates on
multiple lines
@Component({
template: `
<div>
<p>Welcome {{user.username}}</p>
<input [(ngModel)]="user.username" />
<input type="password" [(ngModel)]="user.password" />
<input type="button" (click)="login()" value="login"/>
</div>
`
})
Once Again
Back Ticks, NOT single quotes
– With quotes you have to write everything on one line
` ≠ '
Component View
One-way bindings update the View from the Component
– No side effects are allowed
– In other words View cannot update Component using this mechanism
Types
– Interpolation
– Property Binding
– Attribute
Component View
Interpolation
– format:{{template expression}}
– Displays data from the component
Template expression is often a model property
<h1>The Pizza Place of {{owner}}</h1>
<p>{{current.name}}</p>
<img src="{{current.imagePath}}" />
Could be an expression as well
– Inserts result as a string
<p>5+25={{5+25}}</p>
Template Expressions
JS expressions with side effects are NOT valid template expressions
– assignments (=, +=, -=)
– the 'new' operator
– chaining expressions with ; or ,
– increment and decrement operators (++ and --)
Other invalid JS expressions
– No support for bitwise operators | and &
– No access to global variables (document)
– No side-effects are allowed
Best practice: keep it simple!
– If it's hard, do it in code
The Elvis operator ?
Convenient syntax to avoid null and undefined checks
E.g.
– firstName is allowed to be null or undefined blank
– If owner is null error!
<h1>The Pizza Place of {{owner.firstName}}</h1>
– Add null check
<h1>The Pizza Place of {{owner && owner.firstName}}</h1>
<h1>The Pizza Place of {{owner?.firstName}}</h1>
Property Binding
Property Bindings set a property of a view element
– [property]="template expression" or
– bind-property="template expression"
<input type="button" [value]="orderText" />
This can also be used to pass along complex data to another component
– Only used as input, not as in-out
<pizza-detail [pizza]="current"></pizza-detail>
Property Binding
Template expression may also hold a directive
– Angular will always try to match a directive first, if not known, will assume that it's a
property
<input type="button" [ngClass]="classes" />
Property Binding
Properties are NOT attributes
attribute
<input type="checkbox" disabled="disabled"/>
input.disabled = true; property
The property binding binds to properties! Not attributes
<input type="checkbox" [disabled]="isValid"/>
boolean!
Property Binding
Property Binding versus Interpolation
<img src="{{current.imagePath}}" />
<img [src]="current.imagePath" />
Which one is best?
– Answer: it doesn't matter
– At runtime, interpolations are transformed into property bindings
– Interpolation is syntactic sugar
– Take the most readable one
Attribute Binding
Attribute bindings bind to attributes
– [attr.nameOfAttr]="template expression"
– Property bindings are always preferred
– But some attributes have no corresponding property
<!-- Property Binding Fails -->
<tr><td colspan="{{1+1}}">Three-Four</td></tr>
<!-- Attribute Binding to the rescue! -->
<tr><td [attr.colspan]="1 + 1">One-Two</td></tr>
Structural Directives
Structural directives are directives that can modify HTML layout
– They can add/remove/repeat/replace pieces of HTML
Built-in structural directives
– *ngIf
– *ngFor
– *ngSwitch
Example: *ngFor
Repeats a certain template
– *ngFor="let item of collection"
Creates local
variable
<tbody>
<tr *ngFor="let pizza of pizzas">
<td>{{pizza.name}}</td>
<td [class.promo]="pizza.isPromo">{{pizza.price}}</td>
<td>{{pizza.spiciness}}</td> Binds to item
</tr>
</tbody>
Template Reference Variables
A Template Reference Variable is a variable created in a template and
references data
– Syntax: #identifier
Example
<input #newPizza>
<button (click)="addPizza(newPizza.value)">Add</button>
Template Reference Variables
Where does the value come from?
– If a directive is present, the directive is responsible for setting the value
<input [(ngModel)]="tshirt.email"
name="email" type="email"
#email="ngModel">
– If no directive is present, the value is the element itself
<input #newPizza>
Value Conversion
Binding result depends on a Model’s value, but is not the value itself
– Use a converter function
– function is reevaluated when dependency gets modified
export class AppComponent {
getSpicinessImageUrl(spiciness: number) : string {
if (spiciness == 1) {
return '/images/spicy.jpg';
} else if (spiciness > 1) {
return '/images/hot.jpg';
} else {
return '';
}
}
}
<img [src]="getSpicinessImageUrl(pizza.spiciness)" />
Value Conversion
In the case of formatting Pipes are preferred
<td>{{pizza.price | currency:'EUR':'symbol':'1.2-
2'}}</td>
usage of
the currency pipe
"10" "€10.00"
View Component
Bindings to call the Component from the View
– Side effects are allowed
– Models might be updated
– Certain views will be re-rendered
Types
– Event handling
– Two-way binding
Event Handling
Respond to events
– (event)="template statement"
<input (click)="add()" type="button" />
An event may be
– Directive event
– DOM event
$event
– Object that contains information about the event
<input (keyup)="onKey($event)">
onKey(event: KeyboardEvent) {
this.values.push((<HTMLInputElement>event.target).value);
}
Template Statements
Are not the same as template expressions!
– Similar, but does allow side effects
– Actually it should have a side effect
– Component instance or template reference variable as context
Allowed
– Chaining expressions with ; or ,
– Pure assignment (=)
Not allowed
– Operator assignments (+=, -=)
– The 'new' operator
– Increment and decrement operators (++ and --)
– No support for bitwise operators | and &
– No access to global variables (document)
Best practice: keep it simple!
Event Handling
$event
– Object that contains information about the event
– Exact type is determined by the raised event
<input (keyup)="onKey($event)">
onKey(event: KeyboardEvent) {
this.values.push((<HTMLInputElement>event.target).value);
}
Using a template reference variable
<input #box (keyup)="onKey(box.value)">
onKey(value: string) {
this.values.push(value);
}
Event Handling
Key event filtering
– Angular allows us to listen to specific keys instead of all
<input #box (keyup.enter)="onKey(box.value)">
Only called when
user hits enter
Multiple bindings
<input #newPizza
(keyup.enter)="addPizza(newPizza.value)"
(blur)="addPizza(newPizza.value)">
<button (click)=addPizza(newPizza.value)>Add</button>
Two-way Binding
Two-way binding is just the combination of one-way binding with event
handling
Sets value in view
Respond to change
<input [ngModel]="current.name"
(ngModelChange)="current.name=$event">
simplified
<input [(ngModel)]="current.name">
Two-way Binding
First syntax only useful when doing something else than just setting the value
<input [ngModel]="current.name"
(ngModelChange)="validateAndSet($event)">
Remarks
Alternative syntax
– Some people don't like all the [], (), * - stuff
– There is an alternative syntax called canonical syntax
E.g.
– <input #tel> <input ref-tel>
– (click)="add()" on-click="add()"
Summary
The Importance of Binding
– MV* pattern
Component to View
– Types of Bindings
{{}}, [property],[attr.attr-name]
– Using Structural Directives
– Template Reference Variables
– Value Conversion
function, |
View To Component
– Handling Events
(event)
– Two-Way Data Binding
[(banana-in-a-box)]
Summary
{{value}}
[property]="value"
Component
DOM
(event)="handler"
[(ngModel)]="property"