Displaying Data
The live example / download example demonstrates all of the syntax and code
snippets described in this page.
Showing component properties with interpolation
The easiest way to display a component property is to bind the property name through interpolation. With interpolation, you put the property name in the view template, enclosed in double curly braces:{{myHero}}
.When you bootstrap with the
AppComponent
class (in main.ts
), Angular looks for a <app-root>
in the index.html
, finds it, instantiates an instance of AppComponent
, and renders it
inside the <app-root>
tag.Template inline or template file?
You can store your component's template in one of two places. You can define it inline using thetemplate
property, or you can define
the template in a separate HTML file and link to it in
the component metadata using the @Component
decorator's templateUrl
property.Showing an array property with *ngFor
To display a list of heroes, begin by adding an array of hero names to the component and redefinemyHero
to be the first name in the array.<li *ngFor="let hero of heroes">
{{ hero }}
</li>
In this case,
ngFor
is displaying an array, but ngFor
can
repeat items for any iterable object.Conditional display with NgIf
Sometimes an app needs to display a view or a portion of a view only under specific circumstances.<p *ngIf="heroes.length > 3">There are many heroes!</p>
Summary
Now you know how to use:- Interpolation with double curly braces to display a component property.
- ngFor to display an array of items.
- A TypeScript class to shape the model data for your component and display properties of that model.
- ngIf to conditionally display a chunk of HTML based on a boolean expression.
2.Template Syntax
The Angular application manages what the user sees and can do, achieving this through the interaction of a component class instance (the component) and its user-facing template.
In Angular, the component plays the part of the controller/viewmodel in model-view-viewmodel (MVVM), and the template represents the view.
2.1-HTML in templates
HTML is the language of the Angular template. Almost all HTML syntax is valid template syntaxInterpolation ( {{...}} )
You met the double-curly braces of interpolation,{{
and }}
, early in your Angular education.<p>My current hero is {{currentHero.name}}</p>
Template expressions
A template expression produces a value. Angular executes the expression and assigns it to a property of a binding target; the target might be an HTML element, a component, or a directive.The interpolation braces in
{{1 + 1}}
surround the template expression 1 + 1
.
In the property binding section below,
a template expression appears in quotes to the right of the =
symbol as in [property]="expression"
.Expression context
The expression context is typically the component instance. In the following snippets, thetitle
within double-curly braces and the
isUnchanged
in quotes refer to properties of the AppComponent
.{{title}}
<span [hidden]="isUnchanged">changed</span>
An expression may also refer to properties of the template's context
such as a template input variable (let hero
)
or a template reference variable (#heroInput
).<div *ngFor="let hero of heroes">{{hero.name}}</div>
<input #heroInput> {{heroInput.value}}
The context for terms in an expression is a blend of the template variables, the directive's context object (if it has one), and the component's members. If you reference a name that belongs to more than one of these namespaces, the template variable name takes precedence, followed by a name in the directive's context, and, lastly, the component's member names.
Template statements
A template statement responds to an event raised by a binding target such as an element, component, or directive. You'll see template statements in the event binding section, appearing in quotes to the right of the=
symbol as in (event)="statement"
.<button (click)="deleteHero()">Delete hero</button>
A template statement has a side effect. That's the whole point of an event. It's how you update application state from user action.
2.2-Binding syntax: An overview
Data binding is a mechanism for coordinating what users see, with application data values.Angular provides many kinds of data binding.
Binding types can be grouped into three categories distinguished by the direction of data flow: from the source-to-view, from view-to-source, and in the two-way sequence: view-to-source-to-view:
Interpolation,Property,Attribute,Class,Style:
is One-way from data source to view target
{{expression}}
bind-target="expression"
Event:One-way from view target to data source
on-target="statement"
Two-way:
has two-way data direction
[(target)]="expression"
bindon-target="expression"
Binding types other than interpolation have a target name to the left of the equal sign, either surrounded by punctuation (
[]
, ()
) or preceded by a prefix (bind-
, on-
, bindon-
).The target name is the name of a property. It may look like the name of an attribute but it never is. To appreciate the difference, you must develop a new way to think about template HTML.
The first binding you meet might look like this:
<!-- Bind button disabled state to `isUnchanged` property -->
<button [disabled]="isUnchanged">Save</button>
You'll get to that peculiar bracket notation in a moment. Looking beyond it, your intuition suggests that you're binding to the button's
disabled
attribute and setting
it to the current value of the component's isUnchanged
property.Binding targets
The target of a data binding is something in the DOM. Depending on the binding type, the target can be an (element | component | directive) property, an (element | component | directive) event, or (rarely) an attribute name. The following table summarizes:- Property: Element property, Component property, Directive property
- Event: Element event, Component event, Directive event
- Two-way: Event and property
- Attribute: Attribute (the exception)
- Class class property
- Style style property
<button [style.color]="isSpecial ? 'red' : 'green'">
Property binding ( [property] )
Write a template property binding to set a property of a view element. The binding sets the property to the value of a template expression.The most common property binding sets an element property to a component property value. An example is binding the
src
property of an image element to a component's heroImageUrl
property:<img [src]="heroImageUrl">
One-way in
People often describe property binding as one-way data binding because it flows a value in one direction, from a component's data property into a target element property.Binding target
An element property between enclosing square brackets identifies the target property. The target property in the following code is the image element'ssrc
property.<img [src]="heroImageUrl">
Some people prefer the bind-
prefix alternative, known as the canonical form:<img bind-src="heroImageUrl">
Return the proper type
The template expression should evaluate to the type of value expected by the target property. Return a string if the target property expects a string. Return a number if the target property expects a number. Return an object if the target property expects an object.The
hero
property of the HeroDetail
component expects a Hero
object, which is exactly what you're sending in the property binding:<app-hero-detail [hero]="currentHero"></app-hero-detail>
Remember the brackets
The brackets tell Angular to evaluate the template expression. If you omit the brackets, Angular treats the string as a constant and initializes the target property with that string. It does not evaluate the string!Property binding or interpolation?
You often have a choice between interpolation and property binding. The following binding pairs do the same thing:<p><img src="{{heroImageUrl}}"> is the <i>interpolated</i> image.</p>
<p><img [src]="heroImageUrl"> is the <i>property bound</i> image.</p>
<p><span>"{{title}}" is the <i>interpolated</i> title.</span></p>
<p>"<span [innerHTML]="title"></span>" is the <i>property bound</i> title.</p>
Interpolation is a convenient alternative to property binding in many cases.
Attribute, class, and style bindings
The template syntax provides specialized one-way bindings for scenarios less well suited to property binding.Attribute binding
You can set the value of an attribute directly with an attribute binding.for example, Bind
[attr.colspan]
to a calculated value:<table border=1>
<!-- expression calculates colspan=2 -->
<tr><td [attr.colspan]="1 + 1">One-Two</td></tr>
<!-- ERROR: There is no `colspan` property to set!
<tr><td colspan="{{1 + 1}}">Three-Four</td></tr>
-->
<tr><td>Five</td><td>Six</td></tr>
</table>
Class binding
You can add and remove CSS class names from an element'sclass
attribute with
a class binding.Class binding syntax resembles property binding. Instead of an element property between brackets, start with the prefix
class
,
optionally followed by a dot (.
) and the name of a CSS class: [class.class-name]
.<!-- reset/override all class names with a binding -->
<div class="bad curly special"
[class]="badCurly">Bad curly</div>
<!-- toggle the "special" class on/off with a property -->
<div [class.special]="isSpecial">The class binding is special</div>
<!-- binding to `class.special` trumps the class attribute -->
<div class="special"
[class.special]="!isSpecial">This one is not so special</div>
Style binding
You can set inline styles with a style binding.Style binding syntax resembles property binding. Instead of an element property between brackets, start with the prefix
style
,
followed by a dot (.
) and the name of a CSS style property: [style.style-property]
.<button [style.color]="isSpecial ? 'red': 'green'">Red</button>
<button [style.background-color]="canSave ? 'cyan': 'grey'" >Save</button>
Event binding ( (event) )
The bindings directives you've met so far flow data in one direction: from a component to an element.The following event binding listens for the button's click events, calling the component's
onSave()
method whenever a click occurs:<button (click)="onSave()">Save</button>
Target event
A name between parentheses — for example,(click)
—
identifies the target event. In the following example, the target is the button's click event.<button (click)="onSave()">Save</button>
Some people prefer the on-
prefix alternative, known as the canonical form:<button on-click="onSave()">On Save</button>
Element events may be the more common targets, but Angular looks first to see if the name matches an event property
of a known directive, as it does in the following example:<!-- `myClick` is an event on the custom `ClickDirective` -->
<div (myClick)="clickMessage=$event" clickable>click with myClick</div>
If the name fails to match an element event or an output property of a known directive,
Angular reports an “unknown directive” error.$event and event handling statements
In an event binding, Angular sets up an event handler for the target event.When the event is raised, the handler executes the template statement. The template statement typically involves a receiver, which performs an action in response to the event, such as storing a value from the HTML control into a model.
The binding conveys information about the event, including data values, through an event object named
$event
.Consider this example:
<input [value]="currentHero.name"
(input)="currentHero.name=$event.target.value" >
This code sets the input box value
property by binding to the name
property.
To listen for changes to the value, the code binds to the input box's input
event.
When the user makes changes, the input
event is raised, and the binding executes
the statement within a context that includes the DOM event object, $event
.To update the
name
property, the changed text is retrieved by following the path $event.target.value
.Two-way binding ( [(...)] )
You often want to both display a data property and update that property when the user makes changes.On the element side that takes a combination of setting a specific element property and listening for an element change event.
Angular offers a special two-way data binding syntax for this purpose,
[(x)]
.
The [(x)]
syntax combines the brackets
of property binding, [x]
, with the parentheses of event binding, (x)
.The
[(x)]
syntax is easy to demonstrate when the element has a settable property called x
and a corresponding event named xChange
.
Here's a SizerComponent
that fits the pattern.
It has a size
value property and a companion sizeChange
event:Here's an example in which the
AppComponent.fontSizePx
is two-way bound to the SizerComponent
:<app-sizer [(size)]="fontSizePx"></app-sizer>
<div [style.font-size.px]="fontSizePx">Resizable Text</div>
The
AppComponent.fontSizePx
establishes the initial SizerComponent.size
value.
Clicking the buttons updates the AppComponent.fontSizePx
via the two-way binding.
The revised AppComponent.fontSizePx
value flows through to the style binding,
making the displayed text bigger or smaller.<app-sizer [size]="fontSizePx" (sizeChange)="fontSizePx=$event"></app-sizer>
$event
variable contains the payload of the SizerComponent.sizeChange
event.
Angular assigns the $event
value to the AppComponent.fontSizePx
when the user clicks the buttons.Built-in directives
Earlier versions of Angular included over seventy built-in directives. The community contributed many more, and countless private directives have been created for internal applications.This segment reviews some of the most frequently used built-in directives, classified as either attribute directives or structural directives.
Built-in attribute directives
Attribute directives listen to and modify the behavior of other HTML elements, attributes, properties, and components. They are usually applied to elements as if they were HTML attributes, hence the name.Many details are covered in the Attribute Directives guide. Many NgModules such as the
RouterModule
and the FormsModule
define their own attribute directives.
This section is an introduction to the most commonly used attribute directives:NgClass
- add and remove a set of CSS classesNgStyle
- add and remove a set of HTML stylesNgModel
- two-way data binding to an HTML form element
<input [(ngModel)]="currentHero.name">
FormsModule is required to use ngModel
Before using thengModel
directive in a two-way data binding,
you must import the FormsModule
and add it to the NgModule's imports
list.
Learn more about the FormsModule
and ngModel
in the
Forms guide.Built-in structural directives
Structural directives are responsible for HTML layout. They shape or reshape the DOM's structure, typically by adding, removing, and manipulating the host elements to which they are attached.The deep details of structural directives are covered in the Structural Directives guide where you'll learn:
- why you prefix the directive name with an asterisk (*).
- to use
<ng-container>
to group elements when there is no suitable host element for the directive. - how to write your own structural directive.
- that you can only apply one structural directive to an element.
NgIf
- conditionally add or remove an element from the DOMNgSwitch
- a set of directives that switch among alternative views- NgForOf - repeat a template for each item in a list
Template input variables
Thelet
keyword before hero
creates a template input variable called hero
.
The NgForOf
directive iterates over the heroes
array returned by the parent component's heroes
property
and sets hero
to the current item from the array during each iteration.You reference the
hero
input variable within the NgForOf
host element
(and within its descendants) to access the hero's properties.
Here it is referenced first in an interpolation
and then passed in a binding to the hero
property of the <hero-detail>
component.<div *ngFor="let hero of heroes">{{hero.name}}</div>
<app-hero-detail *ngFor="let hero of heroes" [hero]="hero"></app-hero-detail>
Learn more about template input variables in the Structural Directives guide.
Template reference variables ( #var )
A template reference variable is often a reference to a DOM element within a template. It can also be a reference to an Angular component or directive or a web component.Use the hash symbol (#) to declare a reference variable. The
#phone
declares a phone
variable on an <input>
element.<input #phone placeholder="phone number">
You can refer to a template reference variable anywhere in the template.
The phone
variable declared on this <input>
is
consumed in a <button>
on the other side of the template<input #phone placeholder="phone number">
<!-- lots of other elements -->
<!-- phone refers to the input element; pass its `value` to an event handler -->
<button (click)="callPhone(phone.value)">Call</button>
How a reference variable gets its value
phone
refers to the phone number <input>
box.
The phone button click handler passes the input value to the component's callPhone
method.
But a directive can change that behavior and set the value to something else, such as itself.
The NgForm
directive does that.Template reference variable warning notes
A template reference variable (#phone
) is not the same as a template input variable (let phone
)
such as you might see in an *ngFor
.
Learn the difference in the Structural Directives guide.The scope of a reference variable is the entire template. Do not define the same variable name more than once in the same template. The runtime value will be unpredictable.
You can use the
ref-
prefix alternative to #
.
This example declares the fax
variable as ref-fax
instead of #fax
.<input ref-fax placeholder="fax number">
<button (click)="callFax(fax.value)">Fax</button>
Input and Output properties
An Input property is a settable property annotated with an@Input
decorator.
Values flow into the property when it is data bound with a property bindingAn Output property is an observable property annotated with an
@Output
decorator.
The property almost always returns an Angular EventEmitter
.
Values flow out of the component as events bound with an event binding.You can only bind to another component or directive through its Input and Output properties.
The pipe operator ( | )
The result of an expression might require some transformation before you're ready to use it in a binding. For example, you might display a number as a currency, force text to uppercase, or filter a list and sort it.Angular pipes are a good choice for small transformations such as these. Pipes are simple functions that accept an input value and return a transformed value. They're easy to apply within template expressions, using the pipe operator (
|
):<div>Title through uppercase pipe: {{title | uppercase}}</div>
The pipe operator passes the result of an expression on the left to a pipe function on the right.You can chain expressions through multiple pipes:
<!-- Pipe chaining: convert title to uppercase, then to lowercase -->
<div>
Title through a pipe chain:
{{title | uppercase | lowercase}}
</div>
And you can also apply parameters to a pipe:<!-- pipe with configuration argument => "February 25, 1970" -->
<div>Birthdate: {{currentHero?.birthdate | date:'longDate'}}</div>
The json
pipe is particularly helpful for debugging bindings:<div>{{currentHero | json}}</div>
The generated output would look something like this{ "id": 0, "name": "Hercules", "emotion": "happy",
"birthdate": "1970-02-25T08:00:00.000Z",
"url": "http://www.imdb.com/title/tt0065832/",
"rate": 325 }
3.User Input
User actions such as clicking a link, pushing a button, and entering text raise DOM events. This page explains how to bind those events to component event handlers using the Angular event binding syntax.Run the
Binding to user input events
You can use Angular event bindings to respond to any DOM event. Many DOM events are triggered by user input. Binding to these events provides a way to get input from the user.To bind to a DOM event, surround the DOM event name in parentheses and assign a quoted template statement to it.
The following example shows an event binding that implements a click handler:
<button (click)="onClickMe()">Click me!</button>
The
(click)
to the left of the equals sign identifies the button's click event as the target of the binding.
The text in quotes to the right of the equals sign
is the template statement, which responds
to the click event by calling the component's onClickMe
method.Get user input from the $event object
DOM events carry a payload of information that may be useful to the component. This section shows how to bind to thekeyup
event of an input box to get the user's input after each keystroke.The following code listens to the
keyup
event and passes the entire event payload ($event
) to the component event handler.template: `
<input (keyup)="onKey($event)">
<p>{{values}}</p>
`
When a user presses and releases a key, the keyup
event occurs, and Angular provides a corresponding
DOM event object in the $event
variable which this code passes as a parameter to the component's onKey()
method.export class KeyUpComponent_v1 {
values = '';
onKey(event: any) { // without type info
this.values += event.target.value + ' | ';
}
}
The properties of an $event
object vary depending on the type of DOM event. For example,
a mouse event includes different information than an input box editing event.All standard DOM event objects have a
target
property, a reference to the element that raised the event.
In this case, target
refers to the <input>
element and
event.target.value
returns the current contents of that element.Type the $event
The example above casts the$event
as an any
type.
That simplifies the code at a cost.
There is no type information
that could reveal properties of the event object and prevent silly mistakes.The following example rewrites the method with types:
export class KeyUpComponent_v1 {
values = '';
onKey(event: KeyboardEvent) { // with type info
this.values += (<HTMLInputElement>event.target).value + ' | ';
}
}
The
$event
is now a specific KeyboardEvent
.
Not all elements have a value
property so it casts target
to an input element.Get user input from a template reference variable
There's another way to get the user data: use Angular template reference variables. These variables provide direct access to an element from within the template. To declare a template reference variable, precede an identifier with a hash (or pound) character (#).
Key event filtering (with key.enter
)
The (keyup)
event handler hears every keystroke.
Sometimes only the Enter key matters, because it signals that the user has finished typing.
One way to reduce the noise would be to examine every $event.keyCode
and take action only when the key is Enter.On blur
In the previous example, the current state of the input box is lost if the user mouses away and clicks elsewhere on the page without first pressing Enter. The component'svalue
property is updated only when the user presses Enter.To fix this issue, listen to both the Enter key and the blur event.
4.Lifecycle Hooks
A component has a lifecycle managed by Angular.Angular creates it, renders it, creates and renders its children, checks it when its data-bound properties change, and destroys it before removing it from the DOM.
Angular offers lifecycle hooks that provide visibility into these key life moments and the ability to act when they occur.
A directive has the same set of lifecycle hooks.
Component lifecycle hooks overview
Directive and component instances have a lifecycle as Angular creates, updates, and destroys them. Developers can tap into key moments in that lifecycle by implementing one or more of the lifecycle hook interfaces in the Angularcore
library.Each interface has a single hook method whose name is the interface name prefixed with
ng
.
For example, the OnInit
interface has a hook method named ngOnInit()
that Angular calls shortly after creating the component:Lifecycle sequence
After creating a component/directive by calling its constructor, Angular calls the lifecycle hook methods in the following sequence at specific moments:ngOnChanges()
ngOnInit()
ngDoCheck()
ngAfterContentInit()
ngAfterContentChecked()
ngAfterViewInit()
ngAfterViewChecked()
ngOnDestroy()
Interfaces are optional (technically)
The interfaces are optional for JavaScript and Typescript developers from a purely technical perspective. The JavaScript language doesn't have interfaces. Angular can't see TypeScript interfaces at runtime because they disappear from the transpiled JavaScript.Fortunately, they aren't necessary. You don't have to add the lifecycle hook interfaces to directives and components to benefit from the hooks themselves.
Angular instead inspects directive and component classes and calls the hook methods if they are defined. Angular finds and calls methods like
ngOnInit()
, with or without the interfaces.Spying OnInit and OnDestroy
Go undercover with these two spy hooks to discover when an element is initialized or destroyed.This is the perfect infiltration job for a directive. The heroes will never know they're being watched.
Kidding aside, pay attention to two key points:
-
Angular calls hook methods for directives as well as components.
-
A spy directive can provide insight into a DOM object that you cannot change directly.
Obviously you can't touch the implementation of a native
<div>
. You can't modify a third party component either. But you can watch both with a directive.
The sneaky spy directive is simple, consisting almost entirely of
ngOnInit()
and ngOnDestroy()
hooks
that log messages to the parent via an injected LoggerService
.OnInit()
UsengOnInit()
for two main reasons:- To perform complex initializations shortly after construction.
- To set up the component after Angular sets the input properties.
OnDestroy()
Put cleanup logic inngOnDestroy()
, the logic that must run before Angular destroys the directive.OnChanges()
Angular calls itsngOnChanges()
method whenever it detects changes to input properties of the component (or directive).
This example monitors the OnChanges
hook.DoCheck()
Use theDoCheck
hook to detect and act upon changes that Angular doesn't catch on its own.
Use this method to detect a change that Angular overlooked.
AfterView
The AfterView sample explores theAfterViewInit()
and AfterViewChecked()
hooks that Angular calls
after it creates a component's child views.AfterContent
The AfterContent sample explores theAfterContentInit()
and AfterContentChecked()
hooks that Angular calls
after Angular projects external content into the component.Content projection
Content projection is a way to import HTML content from outside the component and insert that content into the component's template in a designated spot.
AngularJS developers know this technique as transclusion.
AfterContent hooks
AfterContent hooks are similar to the AfterView hooks. The key difference is in the child component.-
The AfterView hooks concern
ViewChildren
, the child components whose element tags appear within the component's template.
-
The AfterContent hooks concern
ContentChildren
, the child components that Angular projected into the component.
5.Component Interaction
This cookbook contains recipes for common component communication scenarios in which two or more components share information.See the
Pass data from parent to child with input binding
HeroChildComponent
has two input properties,
typically adorned with @Input decorations.export class HeroChildComponent {
@Input() hero: Hero;
@Input('master') masterName: string;
}
The second @Input
aliases the child component property name masterName
as 'master'
.The
HeroParentComponent
nests the child HeroChildComponent
inside an *ngFor
repeater,
binding its master
string property to the child's master
alias,
and each iteration's hero
instance to the child's hero
property.export class HeroParentComponent {
heroes = HEROES;
master = 'Master';
}
<app-hero-child *ngFor="let hero of heroes"
[hero]="hero"
[master]="master">
</app-hero-child>
Intercept input property changes with a setter
Use an input property setter to intercept and act upon a value from the parentIntercept input property changes with ngOnChanges()
Detect and act upon changes to input property values with thengOnChanges()
method of the OnChanges
lifecycle hook interface.Parent listens for child event
The child component exposes anEventEmitter
property with which it emits
events when something happens.
The parent binds to that event property and reacts to those events.The child's
EventEmitter
property is an output property,
typically adorned with an @Output decoration
as seen in this VoterComponent
:Clicking a button triggers emission of a
true
or false
, the boolean payload.The parent
VoteTakerComponent
binds an event handler called onVoted()
that responds to the child event
payload $event
and updates a counter.The framework passes the event argument—represented by
$event
—to the handler method,
and the method processes it.Parent interacts with child via local variable
A parent component cannot use data binding to read child properties or invoke child methods. You can do both by creating a template reference variable for the child element and then reference that variable within the parent template as seen in the following example.The following is a child
CountdownTimerComponent
that repeatedly counts down to zero and launches a rocket.
It has start
and stop
methods that control the clock and it displays a
countdown status message in its own template.
The CountdownLocalVarParentComponent
that hosts the timer component is as follows:
- import { Component } from '@angular/core';
- import { CountdownTimerComponent } from './countdown-timer.component';
-
- @Component({
- selector: 'app-countdown-parent-lv',
- template: `
- <h3>Countdown to Liftoff (via local variable)</h3>
- <button (click)="timer.start()">Start</button>
- <button (click)="timer.stop()">Stop</button>
- <div class="seconds">{{timer.seconds}}</div>
- <app-countdown-timer #timer></app-countdown-timer>
- `,
- styleUrls: ['../assets/demo.css']
- })
- export class CountdownLocalVarParentComponent { }
The parent component cannot data bind to the child's
start
and stop
methods nor to its seconds
property.You can place a local variable,
#timer
, on the tag <countdown-timer>
representing the child component.
That gives you a reference to the child component and the ability to access
any of its properties or methods from within the parent template.This example wires parent buttons to the child's
start
and stop
and
uses interpolation to display the child's seconds
property.Parent calls an @ViewChild()
The local variable approach is simple and easy. But it is limited because the parent-child wiring must be done entirely within the parent template. The parent component itself has no access to the child.You can't use the local variable technique if an instance of the parent component class must read or write child component values or must call child component methods.
When the parent component class requires that kind of access, inject the child component into the parent as a ViewChild.
The following example illustrates this technique with the same Countdown Timer example. Neither its appearance nor its behavior will change. The child CountdownTimerComponent is the same as well.
The switch from the local variable to the ViewChild technique
is solely for the purpose of demonstration.
Parent and children communicate via a service
A parent component and its children share a service whose interface enables bi-directional communication within the family.The scope of the service instance is the parent component and its children. Components outside this component subtree have no access to the service or their communications.
This
MissionService
connects the MissionControlComponent
to multiple AstronautComponent
children.6.Component Styles
Angular applications are styled with standard CSS. That means you can apply everything you know about CSS stylesheets, selectors, rules, and media queries directly to Angular applications.Additionally, Angular can bundle component styles with components, enabling a more modular design than regular stylesheets.
This page describes how to load and apply these component styles.
You can run the
Using component styles
For every Angular component you write, you may define not only an HTML template, but also the CSS styles that go with that template, specifying any selectors, rules, and media queries that you need.One way to do this is to set the
styles
property in the component metadata.
The styles
property takes an array of strings that contain CSS code.Style scope
The styles specified in
@Component
metadata apply only within the template of that component.Special selectors
Component styles have a few special selectors from the world of shadow DOM style scoping (described in the CSS Scoping Module Level 1 page on the W3C site). The following sections describe these selectors.Loading component styles
There are several ways to add styles to a component:- By setting
styles
orstyleUrls
metadata. - Inline in the template HTML.
- With CSS imports.
The scoping rules outlined earlier apply to each of these loading patterns.
styles: ['h1 { font-weight: normal; }']
styleUrls: ['./hero-app.component.css']
template: `
<style>
button {
background-color: white;
border: 1px solid #777;
}
</style>
<h3>Controls</h3>
<button (click)="activate()">Activate</button>
Template link tags
You can also write<link>
tags into the component's HTML template.<link rel="stylesheet" href="../assets/hero-team.component.css">
CSS @imports
You can also import CSS files into the CSS files using the standard CSS@import
rule.
For details, see @import
on the MDN site.In this case, the URL is relative to the CSS file into which you're importing.
/* The AOT compiler needs the `./` to show that this is local */
@import './hero-details-box.css';
Non-CSS style files
If you're building with the CLI, you can write style files in sass, less, or stylus and specify those files in the@Component.styleUrls
metadata with the appropriate extensions (.scss
, .less
, .styl
) as in the following example:@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
...
The CLI build process runs the pertinent CSS preprocessor.When generating a component file with
ng generate component
, the CLI emits an empty CSS styles file (.css
) by default.
You can configure the CLI to default to your preferred CSS preprocessor
as explained in the CLI documentation.
Style strings added to the
@Component.styles
array must be written in CSS because the CLI cannot apply a preprocessor to inline styles.7.Angular Elements Overview
Angular elements are Angular components packaged as custom elements, a web standard for defining new HTML elements in a framework-agnostic way.Custom elements are a Web Platform feature currently supported by Chrome, Opera, and Safari, and available in other browsers through polyfills (see Browser Support). A custom element extends HTML by allowing you to define a tag whose content is created and controlled by JavaScript code. The browser maintains a
CustomElementRegistry
of defined custom elements (also called Web Components), which maps an instantiable JavaScript class to an HTML tag.The
@angular/elements
package exports a createCustomElement()
API that provides a bridge from Angular's component interface and change detection functionality to the built-in DOM API.Transforming a component to a custom element makes all of the required Angular infrastructure available to the browser. Creating a custom element is simple and straightforward, and automatically connects your component-defined view with change detection and data binding, mapping Angular functionality to the corresponding native HTML equivalents.
Use the
createCustomElement()
function to convert a component into a class that can be registered with the browser as a custom element.Transforming components to custom elements
Angular provides the
createCustomElement()
function for converting an Angular component,
together with its dependencies, to a custom element. The function collects the component's
observable properties, along with the Angular functionality the browser needs to
create and destroy instances, and to detect and respond to changes.Mapping
A custom element hosts an Angular component, providing a bridge between the data and logic defined in the component and standard DOM APIs. Component properties and logic maps directly into HTML attributes and the browser's event system.Example: A Popup Service
Previously, when you wanted to add a component to an app at runtime, you had to define a dynamic component. The app module would have to list your dynamic component underentryComponents
,
so that the app wouldn't expect it to be present at startup, and then
you would have to load it, attach it to an element in the DOM, and wire
up all of the dependencies, change detection, and event handling, as
described in Dynamic Component Loader.Using an Angular custom element makes the process much simpler and more transparent, by providing all of the infrastructure and framework automatically—all you have to do is define the kind of event handling you want. (You do still have to exclude the component from compilation, if you are not going to use it in your app.)
The Popup Service example app (shown below) defines a component that you can either load dynamically or convert to a custom element.
Typings for custom elements
Generic DOM APIs, such asdocument.createElement()
or document.querySelector()
, return an element type that is appropriate for the specified arguments. For example, calling document.createElement('a')
will return an HTMLAnchorElement
, which TypeScript knows has an href
property. Similarly, document.createElement('div')
will return an HTMLDivElement
, which TypeScript knows has no href
property.When called with unknown elements, such as a custom element name (
popup-element
in our example), the methods will return a generic type, such as HTMLELement
, since TypeScript can't infer the correct type of the returned element.Custom elements created with Angular extend
NgElement
(which in turn extends HTMLElement
). Additionally, these custom elements will have a property for each input of the corresponding component. For example, our popup-element
will have a message
property of type string
.8.Dynamic Component Loader
Component templates are not always fixed. An application may need to load new components at runtime.This cookbook shows you how to use
ComponentFactoryResolver
to add components dynamically.See the
The anchor directive
Before you can add components you have to define an anchor point to tell Angular where to insert components.Loading components
Most of the ad banner implementation is inad-banner.component.ts
.
To keep things simple in this example, the HTML is in the @Component
decorator's template
property as a template string.The
<ng-template>
element is where you apply the directive you just made.
To apply the AdDirective
, recall the selector from ad.directive.ts
,
ad-host
. Apply that to <ng-template>
without the square brackets. Now Angular knows
where to dynamically load components.9.Attribute Directives
An Attribute directive changes the appearance or behavior of a DOM element.Try the
Directives overview
There are three kinds of directives in Angular:- Components—directives with a template.
- Structural directives—change the DOM layout by adding and removing DOM elements.
- Attribute directives—change the appearance or behavior of an element, component, or another directive.
Structural Directives change the structure of the view. Two examples are NgFor and NgIf. Learn about them in the Structural Directives guide.
Attribute directives are used as attributes of elements. The built-in NgStyle directive in the Template Syntax guide, for example, can change several element styles at the same time.
You can tell if
@Input
is needed by the position of the property name in a binding.-
When it appears in the template expression to the right of the equals (=),
it belongs to the template's component and does not require the
@Input
decorator.
-
When it appears in square brackets ([ ]) to the left of the equals (=),
the property belongs to some other component or directive;
that property must be adorned with the
@Input
decorator.
10.Structural Directives
This guide looks at how Angular manipulates the DOM with structural directives and how you can write your own structural directives to do the same thing.Try the
What are structural directives?
Structural directives are responsible for HTML layout. They shape or reshape the DOM's structure, typically by adding, removing, or manipulating elements.As with other directives, you apply a structural directive to a host element. The directive then does whatever it's supposed to do with that host element and its descendants.
Structural directives are easy to recognize. An asterisk (*) precedes the directive attribute name as in this example.
<div *ngIf="hero" class="name">{{hero.name}}</div>
No brackets. No parentheses. Just
*ngIf
set to a string.
There are two other kinds of Angular directives, described extensively elsewhere:
(1) components and (2) attribute directives.
A component manages a region of HTML in the manner of a native HTML element. Technically it's a directive with a template.
An attribute directive changes the appearance or behavior of an element, component, or another directive. For example, the built-in
You can apply many attribute directives to one host element. You can only apply one structural directive to a host element.
A component manages a region of HTML in the manner of a native HTML element. Technically it's a directive with a template.
An attribute directive changes the appearance or behavior of an element, component, or another directive. For example, the built-in
NgStyle
directive
changes several element styles at the same time.You can apply many attribute directives to one host element. You can only apply one structural directive to a host element.
The asterisk (*) prefix
Surely you noticed the asterisk (*) prefix to the directive name and wondered why it is necessary and what it does.Here is
*ngIf
displaying the hero's name if hero
exists.<div *ngIf="hero" class="name">{{hero.name}}</div>
The asterisk is "syntactic sugar" for something a bit more complicated.
Internally, Angular translates the *ngIf
attribute into a <ng-template>
element, wrapped around the host element, like this.<ng-template [ngIf]="hero">
<div class="name">{{hero.name}}</div>
</ng-template>
- The
*ngIf
directive moved to the<ng-template>
element where it became a property binding,[ngIf]
. - The rest of the
<div>
, including its class attribute, moved inside the<ng-template>
element.
Microsyntax
The Angular microsyntax lets you configure a directive in a compact, friendly string. The microsyntax parser translates that string into attributes on the<ng-template>
:-
The
let
keyword declares a template input variable that you reference within the template. The input variables in this example arehero
,i
, andodd
. The parser translateslet hero
,let i
, andlet odd
into variables named,let-hero
,let-i
, andlet-odd
.
-
The microsyntax parser takes
of
andtrackBy
, title-cases them (of
->Of
,trackBy
->TrackBy
), and prefixes them with the directive's attribute name (ngFor
), yielding the namesngForOf
andngForTrackBy
. Those are the names of twoNgFor
input properties . That's how the directive learns that the list isheroes
and the track-by function istrackById
.
-
As the
NgFor
directive loops through the list, it sets and resets properties of its own context object. These properties includeindex
andodd
and a special property named$implicit
.
-
The
let-i
andlet-odd
variables were defined aslet i=index
andlet odd=odd
. Angular sets them to the current value of the context'sindex
andodd
properties.
-
The context property for
let-hero
wasn't specified. Its intended source is implicit. Angular setslet-hero
to the value of the context's$implicit
property whichNgFor
has initialized with the hero for the current iteration.
-
The API guide
describes additional
NgFor
directive properties and context properties.
-
NgFor
is implemented by theNgForOf
directive. Read more about additionalNgForOf
directive properties and context properties NgForOf API reference.
NgIf
and NgForOf
is a great way to learn more.Template input variable
A template input variable is a variable whose value you can reference within a single instance of the template. There are several such variables in this example:hero
, i
, and odd
.
All are preceded by the keyword let
.A template input variable is not the same as a template reference variable, neither semantically nor syntactically.
You declare a template input variable using the
let
keyword (let hero
).
The variable's scope is limited to a single instance of the repeated template.
You can use the same variable name again in the definition of other structural directives.You declare a template reference variable by prefixing the variable name with
#
(#var
).
A reference variable refers to its attached element, component or directive.
It can be accessed anywhere in the entire template.Template input and reference variable names have their own namespaces. The
hero
in let hero
is never the same
variable as the hero
declared as #hero
.Prefer the asterisk (*) syntax.
The asterisk (*) syntax is more clear than the desugared form. Use <ng-container> when there's no single element to host the directive.While there's rarely a good reason to apply a structural directive in template attribute or element form, it's still important to know that Angular creates a
<ng-template>
and to understand how it works.
You'll refer to the <ng-template>
when you write your own structural directive.The <ng-template>
The <ng-template> is an Angular element for rendering HTML. It is never displayed directly. In fact, before rendering the view, Angular replaces the<ng-template>
and its contents with a comment.If there is no structural directive and you merely wrap some elements in a
<ng-template>
,
those elements disappear.
That's the fate of the middle "Hip!" in the phrase "Hip! Hip! Hooray!".<p>Hip!</p>
<ng-template>
<p>Hip!</p>
</ng-template>
<p>Hooray!</p>
Angular erases the middle "Hip!", leaving the cheer a bit less enthusiastic.
You learned
- that structural directives manipulate HTML layout.
- to use
<ng-container>
as a grouping element when there is no suitable host element. - that the Angular desugars asterisk (*) syntax into a
<ng-template>
. - how that works for the
NgIf
,NgFor
andNgSwitch
built-in directives. - about the microsyntax that expands into a
<ng-template>
. - to write a custom structural directive,
UnlessDirective
.
11.Pipes
Every application starts out with what seems like a simple task: get data, transform them, and show them to users. Getting data could be as simple as creating a local variable or as complex as streaming data over a WebSocket.Introducing Angular pipes, a way to write display-value transformations that you can declare in your HTML.
You can run the
Using pipes
A pipe takes in data as input and transforms it to a desired output. In this page, you'll use pipes to transform a component's birthday property into a human-friendly date.import { Component } from '@angular/core';
@Component({
selector: 'app-hero-birthday',
template: `<p>The hero's birthday is {{ birthday | date }}</p>`
})
export class HeroBirthdayComponent {
birthday = new Date(1988, 3, 15); // April 15, 1988
}
Focus on the component's template.<p>The hero's birthday is {{ birthday | date }}</p>
Inside the interpolation expression, you flow the component's
birthday
value through the
pipe operator ( | ) to the Date pipe
function on the right. All pipes work this way.Built-in pipes
Angular comes with a stock of pipes such asDatePipe
, UpperCasePipe
, LowerCasePipe
, CurrencyPipe
, and PercentPipe
.
They are all available for use in any template.
0 comments:
Post a Comment