Angular Component Communication: A Simple Way Now using input() and model()
After going through some latest updates on Angular, I came across this new way of communication between component.
We were using @Input() and @Output() decorators for communication. However, Angular 17 introduced input signals and model() for communication, and I personally loved it’s simplicity.
...
export class CustomSlider {
value = input(0); // TS will conclude type from default value: here it is number
}
Now, you can bind the property in the template:
<custom-slider [value]="40" />
The input() and output() example
I came across a good example here.
You can find the code: https://github.com/lifeatzeron/singal-journey/pull/1
Created a rating component with rating, onRatingChange and ratingChange property
…\components\movie-rating\movie-rating.ts
...
rating = input(4);
ratingChange = output<number>();
onRatingChange(newRating: number) {
this.ratingChange.emit(newRating);
}
...
In the template, used kendo rating to bind the value property with rating() signal, and listen to the valueChange event to trigger the onRatingChange event.
<kendo-rating [value]="rating()" (valueChange)="onRatingChange($event)">
</kendo-rating>
On the app.ts and template we have the following code
interface Movie {
title: string;
rating: number;
}
@Component({
selector: 'app-root',
imports: [RouterOutlet, CounterComponent, MovieRating],
template: `
...
@for (movie of movies(); track movie) {
<h3>{{movie.title}}</h3>
<app-movie-rating [(rating)]="movie.rating"></app-movie-rating>
<p>Current rating: {{movie.rating}} stars</p>
}
`,
styleUrl: './app.scss'
})
export class App {
protected readonly title = signal('singal-journey');
countMe = signal(0);
name = 'Sagar';
movies = signal<Movie[]>([
{ title: 'Dhamal', rating: 4 },
{ title: 'Hera Pheri', rating: 5 },
{ title: 'Hulchal', rating: 5 },
{ title: 'Chup Chup Ke', rating: 3 },
]);
...
}
Now, once you run the code you’ll see the working feature:-
We cleverly implemented bidirectional binding using the input/output signals, but this requires manually handling the input and emitting the output. So, are we clever enough. Let’s think more and move forward with model() now.
Change the type of input to model. The model is a writable signal, so we can update it using the update method.
...
@for (movie of movies(); track movie) {
<h3>{{movie.title}}</h3>
<app-movie-rating [(rating)]="movie.rating"></app-movie-rating>
<p>Current rating: {{movie.rating}} stars</p>
}
...
It automatically emits the value when the signal changes. We no longer need the output for bidirectional communication because the model creates an output for us with the change appended to the name. In our case, it is ratingChange.
