In newer versions of Angular, a pretty significant
change is coming with Signals. If you work with Angular and haven’t heard
about them yet, you’re in the right place. In this video you’ll learn what they are,
at a high level, and you’ll learn how to use the new signal-based inputs along with
the new output function in components. We’re going to take a look at an example
using the existing @Input and @Output decorators and we’ll convert it over to signals and
the output function. I’ve been using signals a lot lately and
I can assure you, It’s a change. Definitely a different way of thinking. Alright, let’s get to it! If you’ve been working in Angular for very
long, you’re surely aware of what change detection is and probably have, at least,
some experience working with it. It can be a challenging thing to deal with
and understand. It can be challenging to optimize too because
many different things can trigger it, or it may not be triggered as expected making it
so changes are not properly reflected in the view. Well, signals have been added in Angular to
address all of this. They are intended to be easier to use and
understand. They are also intended to optimize change
detection by determining the exact parts of the UI that have changed and need to be updated
without affecting others that don’t. A signal is essentially a reactive programming
concept, not really unique in any way to Angular. Their most basic principle is that they will
notify the items using them when their value changes. Under the hood they use a getter function,
and they can be both writable and read-only. So that’s the basic concept of what they
are, and there’s lots to consider when using them. The example that we’ll look at in this video
is just the tip of the iceberg. Signals are going to become a core concept
in the apps we build if they haven’t already. We are moving towards what’s considered
“signal-based” components. What this means is that we will be switching
away from the old @Input and @Output decorators as well as the old lifecycle hooks too. Let’s convert an existing component using
the old @Input decorator over to a signal input to help you better understand the concept. Here we’re looking at our demo application. It allows us to choose from different players
in a list to display a handful of their stats. What we’re looking at here is our player
component. In the code, we have an input using the @Input
decorator for our player data. It takes in a Player object, and it’s required. Now, there are certainly different ways to
do this sort of thing, but for this demo, we have several other properties that are
used to display different player data in the UI. And, in order for these properties to properly
update when the player input data changes, we need to set them in the ngOnChanges lifecycle. If we did in in the OnInit method, it would
only set them the first time the component loads and would not update them when the input
changes. And, what’s happening is that this component
is used in the app component template one time and the player data is updated based
on the player that’s chosen. So, if we didn’t update them on changes,
this wouldn’t work as expected. Ok, so now that we hopefully understand how
this example is working, let’s convert this input over to a signal input instead. Also, when we do this, we’ll covert all
of these properties over to signals and remove the on changes method. Ok, first, we can remove the old decorator. And we can remove it from the imports too
since we’re not going to use it anymore. Now, we can remove the bang, don’t need
that anymore either. To use the new input, we’ll make our player
property equal to input. And we need to make sure that it gets imported
properly too. Just like the old Input decorator, inputs
can be both optional and required so if our player wasn’t required, we would leave this
as is. But, in this case, it’s required, so we
need to add dot, required. And it will be typed to our Player object
so we add angle brackets around our Player interface. Lastly, it’s a function so we need to add
parentheses. And that’s it, this input is now a signal. So, that was pretty easy, but we can see we
have some errors now. If we wanted to leave everything here as is,
we could just update everywhere we use the player object to call the player signal, which
will always give us the current value of that signal. But we don’t want to do this here. Instead, we want to covert all of these properties
over to signals themselves. Let’s start with the image path property. To make this a signal, we can use our player
input. Since we switched it over to a signal, we
can use the new computed function. And we need to make sure that gets imported
correctly too. This function will essentially create a signal
from another signal. And when the original signal value changes,
the computed function will compute its new value, based on the new value of the original
signal. So, within this function, we add a callback. This call back will return our computed value. So, we’ll add our image path here, and then
we just need to add parentheses to call our player signal. So, that’s pretty easy right? Now, every time the player value changes,
this property will automatically update its value too. Ok, one down, a few more to go. Now these others are even easier. For the name, we can add the computed function
again, and then, this time within the call back we can just return the player’s name
from our input signal. And the rest of these will be exactly the
same as this. So, computed function, and then the player
games from the signal. Then, the computed function again, and then
the player points. Then, the computed function again, and then
the player field goal percentage. And then, finally, the computed function,
and the player three point percentage. Ok, now that all of these properties have
been converted to computed signals, we can remove the ngOnChanges method and everything
within it. We can also remove the interface, and the
import as well. Now, the last part here is to properly call
all of these new signals in the template. So, if we switch over to the template, we
need to update every instance of these properties so that they properly call each signal. And that’s it. Now, when the player input changes, all of
the other computed signals will change automatically too and we don’t need to worry about using
ngOnChanges, the changeDetectorRef, or any of that stuff. Ok, so let’s save this and take a look at
how it’s all working. Now, if we got it right, it will just work
like it did before, so it won’t be too exciting. Let’s see. Ok, nice, it’s properly updating the player
component as we change the dropdown value. So, it’s pretty cool that it’s all happening
without us really needing to think about change detection. But we definitely need to think about things
a little differently right? It’s just a different concept for sure. So that’s inputs, but outputs are changing
to signals too. So that’s inputs, but outputs are changing
too. They are simplified with the new output function. For this component, we have an output that
uses an EventEmitter to emit an event with a value of the current player object when
this delete button is clicked. We then react to that event in the app component
to remove that player from the list. But, we no longer want to use the old @Output
decorator, we want to use the new output function, right? Well, to do this, let’s start by removing
the decorator. Let’s remove the import too. Now what’s cool about the new output function
is that we don’t need the EventEmitter anymore either. The event emitting is all handled from this
function now instead. So, let’s remove it. And, let’s remove the import too. Now, we just need to set the playerRemoved
field equal to the new output function. And we need to make sure it gets imported
too. And then, the last part here is to type the
output to the Player object like we had before. Ok now to emit the event, we call it just
as we did the EventEmitter, with the emit function. So, our button can stay as is with this click
event calling the emit function on the output. In fact, we actually don’t need to change
anything else for the output, it all works the same from here. So, let’s save and make sure that players
are still properly getting deleted. Ok, let’s delete Lebron. Nice, looks like he was deleted correctly,
let’s check the dropdown. Yep, not in there anymore either, so it looks
like everything is working correctly now with signals, the signal-based input, and the output
function. So, here in this video, we’ve gotten a little
taste of signals and how they work in Angular. We got a little glimpse into where things
are headed with signal-based components. Hopefully what you saw here will help you
as you build in Angular going forward. Now, there’s still a lot more to signals
like creating writable signals, and using effects, and more, so who knows, maybe I’ll
create some more videos on them in the future. But, that’s all for now. Until next time, thanks for watching.