-
Notifications
You must be signed in to change notification settings - Fork 0
3. Signals
Andrei Antal edited this page Oct 24, 2024
·
2 revisions
In this exercise we will refactor our components to use signals and update the template bindings to use them.
- Update the
MovieListComponentto use a signal for themovies$property, by converting the Observable to a signal using thetoSignalmethod from@angular/core
movies$ = toSignal(
...
);- update the reference in the template to call the signal ->
movies$()
- Change the
movieandeditableinputs from decorated properties to required input signals
movie = input.required<Movie>();
editable = input(true);- update the
commentUpdateandmovieDeleteoutputs from decorated properties to output signals
commentUpdate = output<CommentUpdate>();
movieDelete = output<string>();- create remove existing
movieCommentandcommentSavedproperties and create astatecomputed signal that will hold the movie state (movieCommentandcommentSavedas signals) and change on themovieinput:
state = computed(() => {
const movie = this.movie();
return {
movieComment: signal(movie.comment),
commentSaved: signal(movie.comment.length > 0),
};
});- update the reference in the template to call the signals ->
movie(),editable(),state().commentSaved(),state().movieComment()
- Enable routing component input binding in the
app.config.tsfile:
export const appConfig: ApplicationConfig = {
providers: [
...
provideRouter(
routes,
withComponentInputBinding() // this enables component input binding for route params
),
],
};- We can nou bind directly to the
idurl parameter in theMovieDetailComponentclass using an input signal:
id = input<string>('');- update the
#movievariable to a signal and the#isNewMovieto acomputedsignal that will check if theidis empty (new vs existing movie)
#movie = signal<Movie>(EMPTY_MOVIE);
#isNewMovie = computed(() => !this.id());- Remove the
ngOnInitfunction and use aneffectto update the#moviesignal when theidinput changes
effect((onCleanup) => {
const id = this.id(); // track the id input
if (id) {
const sub = this.#movieService.getMovie(id).subscribe((movie) => { // get the movie from the service
this.movieForm.patchValue(movie);
this.#movie.set(movie);
});
onCleanup(() => sub.unsubscribe()); // cleanup subscription when effect gets disposed
}
});