` element for us.
No need to write it multiple times, or to manually build and concatenate DOM elements in the component's TypeScript code.
---
### Using `ngPlural`
.breadcrumbs[Angular > Models]
While we're at it, let's also add a header above the list:
```html
{{ jokes.length }} jokes
```
You might notice that we'll have a minor problem when there is only one joke.
It will say "1 jokes" instead of "1 joke".
The [`ngPlural`][angular-docs-ng-plural] directive comes to the rescue:
```html
{{ jokes.length }}
* joke
* jokes
```
---
## Pipes
.breadcrumbs[Angular]
When primitive values or objects are interpolated into a template, they are serialized by Angular using their `toString()` method.
That's fine for strings, but not for everything:
* What about **numbers**? You might not want to display all their decimals.
* What about **currencies**? They are usually displayed in a specific format.
* What about **dates**? You might want to use a simple format like `April 15, 1988` rather than the default `Fri Apr 15 1988 00:00:00 GMT-0700 (Pacific Daylight Time)`.
Clearly, some values benefit from a bit of editing.
Pipes allow you to define **reusable value transformations** that you can apply in your HTML templates.
---
### Implementing a pipe
.breadcrumbs[Angular > Pipes]
Let's implement an (amazing) pipe that adds an exclamation point to the end of a string:
```bash
$> ng generate pipe --spec false pipes/exclamation
```
Implement the transformation in the generated file (`src/app/pipes/exclamation.pipe.ts`):
```ts
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'exclamation'
})
export class ExclamationPipe implements PipeTransform {
transform(value: any, args?: any): any {
* return \`${value}!`;
}
}
```
---
### Using a pipe
.breadcrumbs[Angular > Pipes]
Note that Angular automatically registered our pipe in the module's `declarations` array in `src/app/app.module.ts`.
This is necessary to be able to use it in a template:
```ts
// Other imports...
*import { ExclamationPipe } from './pipes/exclamation.pipe';
@NgModule({
declarations: [
AppComponent,
`ExclamationPipe`
],
// ...
})
export class AppModule { }
```
Using the pipe is as simple as "piping" an interpolated value into it with the pipe (`|`) character in a template.
You can do that in `src/app/app.component.html`, then type some text in the input field to see it:
```html
{{ hello(greeting)` | exclamation` }}
```
---
### Pipe parameters
.breadcrumbs[Angular > Pipes]
Pipe can also take **parameters**.
Let's add a number parameter to allow customizing the number of exclamation points in `src/app/pipes/exclamation.pipe.ts`:
```ts
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'exclamation'
})
export class ExclamationPipe implements PipeTransform {
transform(value: any`, strength: number = 1`): any {
* const exclamation = '!'.repeat(strength);
* return \`${value}${exclamation}`;
}
}
```
Parameters are passed to pipes by appending `:value` to them in the template in `src/app/app.component.html`:
```html
{{ hello(greeting) | exclamation`:3` }}
```
---
### Angular built-in pipes
.breadcrumbs[Angular > Pipes]
Angular provides [a few pipes][angular-docs-pipes] out of the box.
Here's some of them:
* [`CurrencyPipe`][angular-docs-currency-pipe]
* [`DatePipe`][angular-docs-date-pipe]
* [`DecimalPipe`][angular-docs-decimal-pipe]
* [`LowerCasePipe`][angular-docs-lowercase-pipe], [`UpperCasePipe`][angular-docs-uppercase-pipe] & [`TitleCasePipe`][angular-docs-titlecase-pipe]
* [`PercentPipe`][angular-docs-percent-pipe]
Here's few usage examples for [`DatePipe`][angular-docs-date-pipe]:
```html
Today is {{ dateValue | date }}
Or if you prefer, {{ dateValue | date:'fullDate' }}
The time is {{ dateValue | date:'shortTime' }}
```
Read [more about pipes][angular-pipes] in the developer guide.
---
## Services
.breadcrumbs[Angular]
Let's do something more interesting: fetch some jokes from the internet.
To do it "The Angular Way", we'll encapsulate that functionality into a **service**.
Why?
**Components** should not try to do too much;
they should focus on **presenting data** and **delegate data access** to specialized classes.
**Services** are here to fill that role.
This helps your components remain as simple as possible while services handle your business logic.
Let's use Angular CLI to generate a joke service:
```bash
$> ng generate service --spec false services/joke
```
(The `--spec false` option disables the generation of an test file for the service.
We will not cover [automated tests][angular-testing] in this tutorial, but you should definitely check it out.)
---
### The joke service
.breadcrumbs[Angular > Services]
The `src/app/services/joke.service.ts` file has been generated:
```ts
import { Injectable } from '@angular/core';
`@Injectable`()
export `class JokeService` {
constructor() { }
}
```
Once again, a service is simply a JavaScript class, annotated with the [`@Injectable`][angular-docs-injectable] decorator.
More about that later.
For now, simply add a method which returns a joke:
```ts
`import { Joke } from '../models/joke';`
@Injectable()
export class JokeService {
constructor() { }
* getJoke(): Joke {
* return { text: 'Knock knock' };
* }
}
```
---
### Providing the joke service
.breadcrumbs[Angular > Services]
To use the service, you must **provide** it in your module's `providers` array in `src/app/app.module.ts`:
```ts
// Other imports...
`import { JokeService } from './services/joke.service';`
@NgModule({
// ...
providers: [
`JokeService`
],
// ...
})
export class AppModule { }
```
---
### Injecting the joke service
.breadcrumbs[Angular > Services]
Once you've done that, you can **inject** it into your component in `src/app/app.component.ts`.
You just have to add a **constructor parameter property**.
While you're at it, also add a **method to add a joke**:
```ts
// Other imports...
*import { JokeService } from './services/joke.service';
export class AppComponent {
// ...
constructor(`private jokeService: JokeService`) {
// ...
}
* addJoke() {
* this.jokes.push(this.jokeService.getJoke());
* }
// ...
}
```
---
#### Calling a method from a button
.breadcrumbs[Angular > Services > Injecting the joke service]
To use our new method,
you can add a button in the template in `src/app/app.component.html`:
```html
```
The `(click)` attribute is Angular's syntax to listen to the `click` event on a DOM element and trigger something when it occurs.
---
### Why does it work?
.breadcrumbs[Angular > Services]
Our component now uses the service.
But why does it work?
All you did was add a parameter property to the constructor:
```ts
constructor(`private jokeService: JokeService`) {
// ...
}
```
As a reminder, in TypeScript this is equivalent to:
```ts
export class AppComponent {
`jokeService: JokeService;`
constructor(`jokeService: JokeService`) {
`this.jokeService = jokeService;`
}
}
```
You **never instantiated the service with `new`**, so where is the instance coming from?
---
### Dependency injection
.breadcrumbs[Angular > Services]
Angular relies on [dependency injection][di] to plug components, services and other elements together.
* After creating your service, you **provided** it in the application **module**.
* This makes it possible for Angular's **injector** to know that your service exists and to create instances of it.
* By adding the parameter to the component's constructor, you **asked Angular to inject** an instance of the service at runtime.
Dependency injection is a form of [inversion of control][ioc],
meaning that parts of your code **receive** the flow of control instead of driving it like in classic procedural programming.
The general goal is to:
* **Decouple** the execution of a task from implementation.
* **Focus** a component on the task it is designed for.
* **Free components from assumptions** about how other systems do what they do and instead rely on **contracts**.
* **Prevent side effects** when **replacing** a component.
---
#### Why dependency injection?
.breadcrumbs[Angular > Services > Dependency injection]
.grid-50[
**Strong coupling**
```js
function Car() {
this.engine = new Engine(24);
}
function Engine(gasLead) {
this.gas = new Gas(gasLead);
}
function Gas(lead) {
this.lead = lead;
}
```
]
.grid-50[
**Loose coupling** (with an *injector*)
```js
function Car(engine) {
this.engine = engine;
}
function Engine(gas) {
this.gas = gas;
}
function Gas(lead) {
this.lead = lead;
}
```
]
---
## Observable data
.breadcrumbs[Angular]
Our current `getJoke()` method has a **synchronous** signature; implying that data is returned right away:
```ts
const joke = jokeService.getJoke();
```
This will **not** work when fetching jokes from a **remote server**, which is inherently an **asynchronous** operation.
The `getJoke()` method must be modified to not immediately return a joke, but to have an asynchronous signature instead.
It could take a **callback** or return a [**Promise**][js-promise].
Another solution is to return an **Observable**.
Angular includes the [RxJS][rxjs] library for reactive programming using Observables,
to make it easier to compose asynchronous or callback-based code.
---
### What (the hell) is an observable?
.breadcrumbs[Angular > Observable data]
An observable is an **asynchronous data stream**, meaning that it allows you to observe **multiple events over time**.
For example, a user's **mouse clicks** on a website could be easily be modeled as an observable:
there will be several of them and they will happen at different times in the future.
---
### What (the hell) is reactive programming?
.breadcrumbs[Angular > Observable data]
Basically, **reactive programming** is programming with **asynchronous** data **streams**.
RxJS is a library which provides an amazing toolbox of functions to **combine, create and filter** any of those streams.
In Angular 2+, many asynchronous operations are represented as Observable streams.
For example, making an **HTTP call** will return an **Observable** which emits either a **response** or an **error**.
You may **subscribe** to that observable to be notified of the result of the asynchronous call.
To learn more about reactive programming,
you may want to read ["The introduction to Reactive Programming you've been missing"][intro-to-reactive-programming].
---
### Making `getJoke()` observable
.breadcrumbs[Angular > Observable data]
Since Angular's `HttpClient` returns **Observables**, that's what we'll use.
For now, let's modify the signature of our `getJoke()` method in `JokeService` in `src/app/services/joke.service.ts` to return an Observable,
without actually making an HTTP call yet:
```ts
// Other imports...
*import { Observable } from 'rxjs/Observable';
*import 'rxjs/add/observable/of';
@Injectable()
export class JokeService {
// ...
getJoke(): `Observable` {
return `Observable.of({ text: 'Knock knock' })`;
}
}
```
`Observable.of` allows us to create a stream which will simply emit the specified value (or values) and complete.
In this case, we created an Observable which will emit one joke.
---
### Subscribing to an Observable
.breadcrumbs[Angular > Observable data]
Of course, the code in our component no longer works now,
since it expects a `Joke` and gets an Observable of a `Joke` instead:
```
ERROR in src/app/app.component.ts(26,21): error TS2345:
Argument of type 'Observable' is not assignable to parameter of type 'Joke'.
Property 'text' is missing in type 'Observable'.
```
Use the `subscribe` method of the Observable to be notified when a Joke is emitted on the stream in `AppComponent` in `src/app/app.component.ts`:
```ts
addJoke() {
* this.jokeService.getJoke().subscribe(joke => {
* this.jokes.push(joke);
* });
}
```
We now have our **asynchronous** implementation:
* We **subscribe** to the Observable when `addJoke` is called.
* But the **callback** adding the new joke into the array will be called **later**,
after the data has been fetched from the remote server.
---
## Making HTTP calls
.breadcrumbs[Angular]
Time to actually fetch some jokes from the internet.
We'll need Angular's [`HttpClient`][angular-docs-http-client].
It is part of `HttpClientModule`,
so we need to provide that to our own application module, `AppModule`, in `src/app/app.module.ts`:
```ts
// Other imports...
*import { HttpClientModule } from '@angular/common/http';
@NgModule({
// ...
imports: [
BrowserModule,
FormsModule,
`HttpClientModule`
],
// ...
})
export class AppModule { }
```
---
### Injecting `HttpClient`
.breadcrumbs[Angular > Making HTTP calls]
Earlier we annotated `JokeService` with the [`@Injectable`][angular-docs-injectable] decorator.
This not only makes it available to the **injector** for creation,
but also allows it to **inject dependencies of its own**.
Now that `HttpClientModule` is available, you can inject `HttpClient` into `JokeService` in `src/app/services/joke.service.ts`:
```ts
// Other imports...
*import { HttpClient } from '@angular/common/http';
@Injectable()
export class JokeService {
constructor(`private httpClient: HttpClient`) { }
// ...
}
```
---
### Joke API response
.breadcrumbs[Angular > Making HTTP calls]
The API we are going to call returns JSON data that looks like this:
```json
{
"type": "success",
"value": {
"categories": [],
"id": 1,
"joke": "Knock knock"
}
}
```
This does not fit our `Joke` model, which only has a `text` property.
---
#### Joke API response model
.breadcrumbs[Angular > Making HTTP calls > Joke API response]
Let's create a new `JokeResponse` model that we can use with this API:
```bash
$> ng generate class models/joke-response
```
This generates a new model file in `src/app/models/joke-response.ts`.
Update it to reflect the **structure** of the API response.
Since it's a nested structure, we'll need **2 classes**:
```ts
export class JokeResponse {
type: string;
value: JokeResponseValue;
}
export class JokeResponseValue {
categories: string[];
id: number;
joke: string;
}
```
---
### Making a GET call
.breadcrumbs[Angular > Making HTTP calls]
We can now update `getJoke()` in `src/app/services/joke.service.ts` to make an actual HTTP call:
```ts
// Other imports...
*import { JokeResponse } from '../models/joke-response';
@Injectable()
export class JokeService {
// ...
getJoke(): Observable {
* return this.httpClient
* .get('https://api.icndb.com/jokes/random');
}
}
```
As you can see, [`HttpClient`][angular-docs-http-client]'s `get` method is **generic**,
and Angular will take care of parsing the response body and giving us an object of the right type.
But we're still left with one problem: we need an Observable of `Joke` objects, and have one of `JokeResponse` objects instead:
```
ERROR in src/app/services/joke.service.ts(15,5): error TS2322:
Type 'Observable' is not assignable to type 'Observable'.
Type 'JokeResponse' is not assignable to type 'Joke'.
Property 'text' is missing in type 'JokeResponse'.
```
---
### Transforming data
.breadcrumbs[Angular > Making HTTP calls]
We need to be able to transform a `JokeResponse` object into a `Joke`.
Let's add a utility function at the bottom of the file in `src/app/services/joke.service.ts`:
```ts
function convertJokeResponseToJoke(response: JokeResponse): Joke {
return {
text: response.value.joke
};
}
```
---
### Transforming Observable streams
.breadcrumbs[Angular > Making HTTP calls]
Similarly to the [`map`][js-array-map] method of JavaScript arrays, Observables have a [`map`][observable-map] operator,
which allows you to transform each item emitted in the stream:
To use it, you need to import it and use the Observable's `pipe` method in `JokeService` in `src/app/services/joke.service.ts`:
```ts
// Other imports...
*import { map } from 'rxjs/operators';
// ...
getJoke(): Observable {
return this.httpClient
.get('https://api.icndb.com/jokes/random')
* .pipe(map(convertJokeResponseToJoke));
}
```
---
### Reacting to errors in observable streams
.breadcrumbs[Angular > Making HTTP calls]
An observable stream may emit an **error**.
You can be notified of that error by passing a second callback function to `subscribe` in `AppComponent` in `src/app/app.component.ts`:
```ts
addJoke() {
this.jokeService.getJoke().subscribe(joke => {
this.jokes.push(joke);
}`, err => {`
`console.warn('Could not get new joke', err);`
`}`);
}
```
For the purpose of testing this new behavior,
you can produce an error by changing the URL in `JokeService`in `src/app/services/joke.service.ts`,
so that the call fails.
You should then see an error in the console when adding a joke:
```ts
getJoke(): Observable {
return this.httpClient
.get('https://`foo.example.com`/jokes/random')
.pipe(map(convertJokeResponseToJoke));
}
```
You can then change it back to the correct URL.
---
### Getting the HTTP response
.breadcrumbs[Angular > Making HTTP calls]
We've seen that by default, Angular's `HttpClient` returns only the **body of the response**
(this is a *generic example*; do **not** make this change to the project):
```ts
function getJoke(): Observable {
return this.httpClient
.get('https://api.icndb.com/jokes/random');
}
getJoke().subscribe(jokeResponse => {
// "jokeResponse" has type JokeResponse
console.log(jokeResponse.value.joke);
// "Chuck Norris can make a class that is both abstract and final."
});
```
That's nice, but in some cases we might need access to the **HTTP status** or **headers** sent by the server in the response.
---
#### Observing the response
.breadcrumbs[Angular > Making HTTP calls > Getting the HTTP response]
To get Angular's `HttpClient` to give you the full [`HttpResponse`][angular-docs-http-response] object,
you need to pass an additional options object to your HTTP call,
with the `observe` property set to `"response"` (this is also a *generic example*):
```ts
function getJoke(): Observable<`HttpResponse`> {
`const options = { observe: 'response' };`
return this.httpClient
.get('https://api.icndb.com/jokes/random'`, options`);
}
getJoke().subscribe(httpResponse => {
// "httpResponse" has type HttpResponse
console.log(httpResponse.status); // 200
// "httpResponse.body" has type JokeResponse
console.log(httpResponse.body.value.joke);
// "Chuck Norris can make a class that is both abstract and final."
});
```
Now, you no longer get an Observable of `JokeResponse` objects,
but instead get an Observable of `HttpResponse` objects.
That is, the full HTTP response, with its `body` already parsed as a `JokeResponse` object.
Read [the documentation of the `HttpResponse` class][angular-docs-http-response] to see what information you can extract from the response.
---
## Component interaction
.breadcrumbs[Angular]
As described earlier, components are Angular's fundamental building blocks.
We're going to add a few features to our application:
* The ability to **vote** on which are the best jokes.
* The ability to see the **total** number of votes and how many votes the **best** joke has had.
* The ability to **clear** all the collected votes.
.grid-50[
We could implement all of this in `AppComponent`,
but that would not be viable in a real-world scenario with more complex features.
When you have a complex page with multiple areas that each have their specific logic,
it's good practice to **isolate each part into a component**:
]
.grid-50[
]
---
### Adding votes to the model
.breadcrumbs[Angular > Component interaction]
Update the `Joke` model in `src/app/models/joke.ts` to have a `votes` property:
```ts
export class Joke {
text: string;
* votes: number;
}
```
You need to update `src/app/app.component.ts` to set the initial votes to `0`:
```ts
this.jokes = [
{ text: 'Knock knock'`, votes: 0` },
{ text: 'The cake is a lie'`, votes: 0` }
];
```
You also need to update the `convertJokeResponseToJoke` function in `src/app/services/joke.service.ts`:
```ts
function convertJokeResponseToJoke(response: JokeResponse): Joke {
return {
text: response.value.joke,
* votes: 0
};
}
```
---
### Creating a child component
.breadcrumbs[Angular > Component interaction]
Let's generate our **new component**, the `JokeComponent`:
```ts
$> ng generate component --spec false components/joke
```
This will create a component in the `src/app/components/joke` directory,
with its own TypeScript definition, HTML template and CSS styles.
---
#### The `JokeComponent`
.breadcrumbs[Angular > Component interaction > Creating a child component]
The responsibility of the new `JokeComponent` will be to display a `Joke` object,
and to provide a button to vote on the joke.
Let's add a `joke` property to the new component in `src/app/components/joke/joke.component.ts`:
```ts
// Other imports...
*import { Joke } from '../../models/joke';
@Component({
selector: 'app-joke',
templateUrl: './joke.component.html',
styleUrls: ['./joke.component.css']
})
export class JokeComponent implements OnInit {
* joke: Joke;
// ...
}
```
And update the component's template in `src/app/components/joke/joke.component.html` to display the joke's text:
```html
{{ joke.text }}
```
---
### Passing data from parent to child with input binding
.breadcrumbs[Angular > Component interaction]
We want the joke to be provided by the parent component, `AppComponent`.
It's an **input** of the `JokeComponent`.
Annotating a component's property with the [`@Input`][angular-docs-input] decorator marks it as an **input property** which can be set by a parent component.
You can do this in `src/app/components/joke/joke.component.ts`:
```ts
// Other imports...
import { Component, `Input`, OnInit } from '@angular/core';
// ...
export class JokeComponent implements OnInit {
`@Input()`
joke: Joke;
// ...
}
```
You can now use the `JokeComponent` in the main component's template in `src/app/app.component.html`.
You need to create an `` tag (matching the component's selector),
and to set the `joke` input property:
```html
```
---
### Voting on jokes
.breadcrumbs[Angular > Component interaction]
Now that `JokeComponent` is working, we can use it to **handle the logic related to one joke**, like voting.
Add a `vote()` method to `JokeComponent` in `src/app/components/joke/joke.component.ts`:
```ts
vote() {
this.joke.votes++;
}
```
Add these 2 lines to the component's template in `src/app/components/joke/joke.component.html`:
```html
{{ joke.text }}
*({{ joke.votes }} votes)
*
```
You can now vote!
---
### Displaying global voting information
.breadcrumbs[Angular > Component interaction]
Let's now display the **total number of votes** and the **best vote** on the page.
That's the job of the **main component**, since a `JokeComponent` only knows about its own joke,
so it can't know the total number of votes or whether its number of votes is the highest.
Add this information to `AppComponent` in `src/app/app.component.ts`:
```ts
export class AppComponent {
// ...
* bestVote: number;
* totalVotes: number;
constructor(private jokeService: JokeService) {
* this.bestVote = 0;
* this.totalVotes = 0;
// ...
}
// ...
}
```
And display it in the template in `src/app/app.component.html`:
```html
Total votes: {{ totalVotes }}, best vote: {{ bestVote }}
```
---
### Output from child components
.breadcrumbs[Angular > Component interaction]
The vote button is in the child component's template, so `AppComponent` can't put an event listener on it directly.
Instead, we need our `JokeComponent` to have an **output** that its parent can listen to.
Annotating a component's property with the [`@Output`][angular-docs-output] decorator marks it as an **output property**.
It must be an [`EventEmitter`][angular-docs-event-emitter] (or an Observable).
Let's add one to `JokeComponent` in `src/app/components/joke/joke.component.ts` now:
```ts
import { Component, `EventEmitter`, Input, OnInit, `Output` } from '@angular/core';
// ...
export class JokeComponent implements OnInit {
// ...
* @Output()
* voted: EventEmitter;
constructor() {
* this.voted = new EventEmitter();
}
vote() {
this.joke.votes++;
* this.voted.emit(this.joke);
}
}
```
---
### Listening to child component events from a parent
.breadcrumbs[Angular > Component interaction]
Let's add an `onJokeVoted()` method to `AppComponent` in `src/app/app.component.ts`:
```ts
onJokeVoted(joke: Joke) {
this.totalVotes++;
if (joke.votes > this.bestVote) {
this.bestVote = joke.votes;
}
}
```
We want this method to be called every time a vote button is clicked in a child `JokeComponent`.
From the parent's point of view, an **output property** of a child component is **just like any other DOM event**.
You bind to it using Angular's `(event)='expression'` syntax, exactly like you bind to `(click)` on a `