)` syntax allows you to **bind functions to events** occurring on a DOM element.
Let's bind the function we just created to `click` events on the `` tag in `src/app/app.component.html`:
```html
Welcome to {{ title }}!
```
You should now see the message being logged in the console when clicking on the title.
---
##### Getting at the event
.breadcrumbs[Angular > Getting started > Data binding > Binding to events]
You might need the actual [event object][dom-event] to get some data out of it (for example, the click coordinates).
Let's update `onTitleClicked()` in `src/app/app.component.ts` so it requires an event parameter and log it:
```ts
export class AppComponent {
// ...
onTitleClicked(`event: MouseEvent`) {
console.log('The title was clicked'`, event`);
}
}
```
To make this work, pass the special `$event` value as an argument to your function call in `src/app/app.component.html`, and Angular will pass the event object to your function:
```html
Welcome to {{ title }}!
```
> Note that you **must** use exactly `$event` as the argument's value
---
#### Interpolation with functions
.breadcrumbs[Angular > Getting started > Data binding]
Interpolation is not limited to simple properties.
You can also use a component's **method** in the template.
Add the following method to the component in `src/app/app.component.ts`:
```ts
export class AppComponent {
// ...
* hello(name: string): string {
* return \`Hello ${name}`;
* }
}
```
Now use that function in the template in `src/app/app.component.html`:
```html
`{{ hello("World") }}`
```
> Change the value passsed to the `hello()` function to see it change.
---
## User input
.breadcrumbs[Angular]
One of the things you will often need to do in your app is **react to user input** (for example, through forms).
Let's make our greeting **dynamic** by adding an input field to customize the name.
Make the following changes to the component in `src/app/app.component.ts`:
```ts
export class AppComponent {
// ...
`greeting: string;`
constructor() {
this.title = 'app';
`this.greeting = '';`
}
// ...
}
```
Now interpolate that new property into the `hello` function in the template in `src/app/app.component.html`:
```html
{{ hello(`greeting`) }}
```
---
### `ngModel`
.breadcrumbs[Angular > User input]
Add an input field to the template above the greeting in `src/app/app.component.html`:
```html
*
*
*
{{ hello(greeting) }}
```
`[(ngModel)]` is Angular's **two-way data binding** syntax.
It binds the `greeting` property to the HTML input field, and _vice-versa_.
You will most likely get this error in the console:
```
Uncaught Error: Template parse errors:
Can't bind to 'ngModel' since it isn't a known property of 'input'.
```
This is because `[(ngModel)]` is provided by the optional `FormsModule`, which you have to _opt in_ to use.
---
#### `FormsModule`
.breadcrumbs[Angular > User input > `ngModel`]
To **import** the module into your application, you must add it to the `imports` array of your own module in `src/app/app.module.ts`:
```ts
// Other imports...
*import { FormsModule } from '@angular/forms';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
`FormsModule`
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
```
Once you've done that, the error should be gone and everything should display as expected.
Now, as you type inside the input field, the `greeting` variable is **automatically kept up-to-date** in the background,
and Angular **updates the template** to reflect the new value.
---
### Two-way data binding
.breadcrumbs[Angular > User input]
.grid-50[
Traditional templating systems bind data **in only one direction**.
The developer has to write code that constantly syncs the view with the model and vice versa.
]
.grid-50[
With Angular (and any two-way binding system), changes are **immediately reflected** in both view and model.
Also note that our **component** is **isolated from and unaware of the view**:
it does not care about DOM manipulation or rendering concerns.
]
---
## Directives
.breadcrumbs[Angular]
Just as **Components** can be seen as **custom HTML tags** that display and behave as defined by their template and class,
**Directives** can be seen as **custom HTML attributes** that can be added to HTML elements (or Angular components) to apply them various effects.
> Technically, a **Directive** is a class decorated with the `@Directive` decorator.
Directives in Angular can be divided into two categories: **structural** and **attribute** directives.
---
### Structural directives
.breadcrumbs[Angular > Directives]
Structural directives have an impact on the HTML layout.
They shape or reshape the **DOM's structure**, typically by **adding, removing, or manipulating elements**.
Let's add the [`ngIf`][angular-docs-ng-if] directive to our template in `src/app/app.component.html` as an example:
```html
{{ hello(greeting) }}
```
> The `*` before `ngIf` in the template is not a typo ; structural directives must **always** be preceeded by a `*`.
As you can see, the entire paragraph is now removed from the DOM as long as the `greeting` property is _falsy_ (e.g. `undefined` or an empty string).
It is added back to the page as soon as `greeting` has a _truthy_ value.
> Read the [documentation][angular-structural-directives] to learn more about structural directives. Many more such directives are provided by Angular out of the box, like [`ngFor`][angular-docs-ng-for] (which we'll use later) and [`ngSwitch`][angular-docs-ng-switch].
---
### Attribute directives
.breadcrumbs[Angular > Directives]
> Want to create your own attributes directives ? See [advanced-angular][advanced-angular-subject]
An **attribute** directive changes the **appearance or behavior of the DOM element** to which it is attached.
Let's say we want to programmatically add or remove classes to our `` tag in our template.
First, open the `src/app/app.component.ts` to add a new property to the component's class called, for example, `titleClasses`:
```ts
export class AppComponent {
// Previous properties
* titleClasses: { [ name: string ]: boolean };
constructor() {
// ...
* this.titleClasses = {
* italic: true,
* hoverable: true
* };
}
// ...
}
```
---
#### Define and bind the classes
.breadcrumbs[Angular > Directives > Attribute directives]
We need to declare those two classes in our component's style. Open the `app.component.scss` file and add them there:
```scss
.italic { font-style: italic; }
.hoverable { cursor: pointer; }
```
Now, we can use Angular's `ngClass` attribute directive to bind the `titleClasses` oject to our `` title:
```html
Welcome to {{ title }}!
```
> For each `titleClasses`'s property whose value is `true`, `ngClass` will add its name to the element as a CSS class of the same name.
> You can try changing the `titleClasses` properties value or add your own to see how that reflects to the element's classes.
---
### Common directives
.breadcrumbs[Angular > Directives]
These common directives are provided by Angular out of the box:
**Structural directives**
- [`ngFor`][angular-docs-ng-for] - Instantiates a template **once per item** from an iterable.
- [`ngIf`][angular-docs-ng-if] - **Conditionally includes** a template based on the value of an expression.
- [`ngSwitch`][angular-docs-ng-switch] - Adds/removes DOM sub-trees when the nest match expressions matches the **switch** expression.
**Attribute directives**
- [`ngClass`][angular-docs-ng-class] - Adds and removes **CSS classes** on an HTML element.
- [`ngModel`][angular-docs-ng-model] - **Two-way binding** between a form's input field and a component's variable.
- [`ngPlural`][angular-docs-ng-plural] - Adds/removes DOM sub-trees based on a numeric value. (Tailored for **pluralization**.)
- [`ngStyle`][angular-docs-ng-style] - Update an HTML element's **styles**.
---
## 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 and that's what Pipes are all about.
They're special functions that your value will pass through before being rendered in the template.
> Want to implement your own pipes? See [advances-angular][advanced-angular-subject]
---
### Use case
.breadcrumbs[Angular > Pipes]
Open the `src/app/app.component.ts` file and add a new `progress` property:
```ts
export class AppComponent {
// Previous properties
* progress: number;
constructor() {
// ...
* this.progress = 0.45;
}
// ...
}
```
We want to display this value as a percentage in our template. We _could_ do it like so:
```html
{{ progress `* 100` }}`%`
```
Doing so implies that we repeat this same snippet each time we want to display a percentage in our app. This is error prone as we might forget the `%`, or add an exceeding `0` when multiplying our value, etc.
We'd be better off having this logic in a `Pipe` so we could use it any time we want.
---
### Using a pipe
.breadcrumbs[Angular > Pipes]
In this case, Angular provides us with a `Pipe` named `percent` that does display values as percentages and thus, can help us rendering our progress percentage in our template.
Actually using the `Pipe` is as simple as providing a value to the `Pipe` using the pipe (`|`) character in a template:
```html
We've only done {{ progress` | percent` }} of those damned slides
```
> You can see that this built-in pipe multiply the given value and add the `%` character at the end.
---
### 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.
---
## Models
.breadcrumbs[Angular]
Now, let's make our application funny by adding some jokes.
It's a good practice to create **types, interfaces or classes** to define the structure of the objects you will manipulate in your application. This will help you avoid mistakes in your code.
Let's start with a very simple one.
Create a new file at `src/app/jokes/joke.ts` with the following content:
```ts
export type Joke = {
`text: string;`
}
```
> **Angular CLI**: Use `ng generate class ` to create the files for a new model class... but that's not very helpful in this case...
---
### Using models
.breadcrumbs[Angular > Models]
Let's add some jokes to our component in `src/app/app.component.ts`:
```ts
// Other imports...
`import { Joke } from './jokes/joke';`
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
// ...previous properties
`jokes: Joke[];` // The jokes property is an array of only Joke-like objects
constructor() {
// ...
* this.jokes = [
* { text: 'Knock knock' },
* { text: 'The cake is a lie' }
* ];
}
// ...
}
```
---
### Using `ngFor`
.breadcrumbs[Angular > Models]
Now that we have some jokes, let's display them.
We want a `` list, with a `- ` item for each joke.
That's a job for the [`ngFor`][angular-docs-ng-for] directive.
Add this at the bottom of the component's template in `src/app/app.component.html`:
```html
```
> The directive handles repeating the `
- ` 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
```
---
## Services
.breadcrumbs[Angular]
Let's do something more interesting: fetch those jokes from the internet rather than hard-coding them in our component.
To do it "The Angular Way", we'll encapsulate that functionality into a **Service**.
Why?
- **Components** should not try to do very 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.
- **Services** can be used by multiples Components, Directives, Pipes, Services, etc, which helps in repeating the same logic.
> **Angular CLI**: Use `ng generate service ` to create all the files for a new service
---
### The joke service
.breadcrumbs[Angular > Services]
Once again, a service is simply a JavaScript class, annotated with the [`@Injectable`][angular-docs-injectable] decorator (more about that later).
Create a new `src/app/jokes/joke.service.ts` file with the following content:
```ts
import { Injectable } from '@angular/core';
`import { Joke } from './joke';`
@Injectable({ providedIn: 'root' })
export class JokeService {
constructor() { }
* getJoke(): Joke {
* return { text: 'Knock knock' };
* }
}
```
> For now, the service only returns a single hard-coded `Joke`. We will actually fetch them from the web later on.
---
### Providing the joke service
.breadcrumbs[Angular > Services]
You may have notice the `providedIn: 'root'` property in the `@Injectable` param object of the generated service.
This particular settings indicates that **the service is provided by the root of your application**, which means that it is accessible to all your `Components`/`Directives`/`Pipes`.
> You might encouter `Services` that do not have this setting in their `@Injectable` decorator (i.e. when using external libraries). If this is the case, you must manually **provide** them in a module's `providers` array:
```ts
// Other imports...
import { SomeService } from "./some/directory";
@NgModule({
// ...
providers: [`SomeService`],
// ...
})
export class SomeModule {}
```
---
### Injecting the joke service
.breadcrumbs[Angular > Services]
Now, you can **reference** the service into your component in `src/app/app.component.ts`.
You just have to add a **constructor parameter property**.
While you're at it, also create a **method to add a joke**:
```ts
// Other imports...
*import { JokeService } from './jokes/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.
- As previously said, your service is **provided** in the **root** of your application.
- This makes it possible for Angular's **injector** to know that your service exists and to create an instance of it.
- By adding the parameter to the component's constructor, you **indicated that Angular should inject** this service instance at runtime.
---
#### 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].
Since Angular uses the [RxJS][rxjs] library internally when handling HTTP requests, our service method should return an `Observable` of a `Joke`.
> To learn more about `Observables` and the `RxJS` library, see [the corresponding subject][rxjs-subject].
---
### Making `getJoke()` observable
.breadcrumbs[Angular > Observable data]
For now, let's modify the signature of our `getJoke()` method in `JokeService` in `src/app/jokes/joke.service.ts` to return an `Observable` of a `Joke`, without actually making an HTTP call yet:
```ts
// Other imports...
*import { Observable, of } from 'rxjs';
@Injectable()
export class JokeService {
// ...
getJoke(): `Observable` {
return `of({ text: 'Knock knock' })`;
}
}
```
> Note the `<>` in `Observable`. `Observable` is what is called a **Generic Type** ; a type that accepts one or more other types to better express what they represent. In this case, it allows us to define that `getJoke()` returns an `Observable` that will emits `Joke` events.
`of` allows us to create an `Observable` which will simply emit the specified values (here, the `Joke`), then complete.
---
### 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` 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'.
```
In `AppComponent` in `src/app/app.component.ts`, use the `subscribe()` method of the returned `Observable` to add the `Joke` to the array once it's emitted :
```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] to do so.
It is part of `HttpClientModule`, so we need to import that into 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 **have dependencies of its own**.
Now that `HttpClientModule` is available, you can inject `HttpClient` into `JokeService` in `src/app/jokes/joke.service.ts`, by adding it to the constructor parameters:
```ts
// Other imports...
*import { HttpClient } from '@angular/common/http';
@Injectable()
export class JokeService {
constructor(`private http: 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.
Since it's a nested structure, we'll need **2 classes**.
Create a new file at `src/app/jokes/joke-response.ts` with the following content:
```ts
export type JokeResponse = {
type: string;
value: JokeResponseValue;
}
export type JokeResponseValue = {
categories: string[];
id: number;
joke: string;
}
```
---
### Making a GET call
.breadcrumbs[Angular > Making HTTP calls]
We can now update `getJoke()` in `src/app/jokes/joke.service.ts` to make an actual HTTP call:
```ts
// Other imports...
*import { JokeResponse } from './joke-response';
@Injectable()
export class JokeService {
// ...
getJoke(): Observable {
* return this.httpClient
* .get('https://api.icndb.com/jokes/random');
}
}
```
> The `HttpClient#get()` method is a **Generic Method** that accepts a type argument between `<...>` to specify the type expected data, here a value matching our `JokeResponse` model.
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/jokes/joke.service.ts`:
```ts
function convertJokeResponseToJoke(response: JokeResponse): Joke {
return {
text: response.value.joke,
};
}
```
Effectively, this function allows mapping a `JokeResponse` to a `Joke`.
---
### Transforming Observable streams
.breadcrumbs[Angular > Making HTTP calls]
Let's use this new mapping function in the method that fetches the joke so that the final Observable it returns is an `Observable`:
```ts
// Other imports...
*import { map } from 'rxjs/operators';
// ...
getJoke(): Observable {
return this.httpClient
.get('https://api.icndb.com/jokes/random')
* .pipe(map(convertJokeResponseToJoke));
}
```
> If you forgot or don't know how this `map` operator works, check out the [RxJS subject][rxjs-subject-map]
---
### 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);`
`}`);
}
```
You can produce an error by changing the URL in `JokeService`in `src/app/jokes/joke.service.ts`,
so that the call fails.
```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.
> In a real application, you should display an error on the screen.
---
## Component interaction
.breadcrumbs[Angular]
As described earlier, components are Angular's fundamental UI 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/jokes/joke.ts` to have a `votes` property:
```ts
export type 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/jokes/joke.service.ts`:
```ts
function convertJokeResponseToJoke(response: JokeResponse): Joke {
return {
text: response.value.joke,
* votes: 0
};
}
```
---
### Creating a component
.breadcrumbs[Angular > Component interaction]
Let's generate a **new component**, `JokeComponent`, whose responsibility will be to properly display a `Joke` object in the page, and provide a button to vote for the joke:
```ts
$> npm run ng generate component jokes/joke --skip-tests
```
This will create a component in the `src/app/jokes/joke` directory,
with its own TypeScript definition, HTML template and CSS styles.
---
#### The `JokeComponent`
.breadcrumbs[Angular > Component interaction > Creating a component]
Let's add an optional `joke` property to the new component in `src/app/jokes/joke/joke.component.ts`:
```ts
// Other imports...
*import { Joke } from 'src/app/jokes/joke';
@Component({
selector: 'app-joke',
templateUrl: './joke.component.html',
styleUrls: ['./joke.component.css']
})
export class JokeComponent implements OnInit {
* joke?: Joke;
// ...
}
```
> Remember that a property defined with a `?` is `undefined` in addition to its defined type.
And update the component's template in `src/app/jokes/joke/joke.component.html` to display the joke's text (if there is a joke to display):
```html
{{ joke.text }}
```
---
### Using our new component
.breadcrumbs[Angular > Component interaction]
As you can see in our component's class, its `selector` has been set to `app-joke`.
This means that we can include our component in another component's template by adding a `` tag.
Let's do so in `src/app/app.component.html`:
```html
```
We can now see on our app page that we have two elements in our list, but that they are empty.
Indeed, we told our `JokeComponent` to display the `joke.text` property in its template, but we didn't actually provide it any `joke` to get the `text` from...
---
### Passing data from parent to child with input binding
.breadcrumbs[Angular > Component interaction]
We want the joke to be provided to the `JokeComponent` as an **input**.
Annotating a component's property with the [`@Input`][angular-docs-input] decorator marks it as an **input property**.
You can do this in `src/app/jokes/joke/joke.component.ts`:
```ts
// Other imports...
import { Component, `Input`, OnInit } from '@angular/core';
// ...
export class JokeComponent implements OnInit {
`@Input()` joke?: Joke;
// ...
}
```
Now, update the main component's template in `src/app/app.component.html` so that it binds each joke object to the `joke` input of the `` tag.
```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/jokes/joke/joke.component.ts`:
```ts
vote() {
if (this.joke) {
this.joke.votes++;
}
}
```
Add these 2 lines to the component's template in `src/app/jokes/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/jokes/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() {
if (this.joke) {
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 `