Angular Signals: The Complete Guide

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Hi Friends In Angular 16, an exciting new  feature has been introduced. Signals. Signals are reactive primitives  that offers granular tracking   of state changes within the application. Signals was introduced in Angular  16 and became stable in Angular 17. In this video I am going to explain some of  the key concepts in Signals, benefits of using   signals and then I am going to show you how to  implement signals in an angular application. Before that, I request you to subscribe  to this channel and support me. Ok. Let's start. To understand about signals, we  need to know about three reactive   primitives. Writable Signals,  Computed Signals and Effects. Writable signals are a specific type of signal   in Angular that allow you to  modify their value directly. Let me explain this using an example. I have created this simple application. In which, I have a button and a count value. On   clicking this button, this  count value will increase. For that, I have created a count  variable and on clicking this button,   I am calling a function and inside this  function, I am just increasing this value. Now, let's change this to a writable signal. How can we change this? We just need to use the signal constructor.  We can also pass the initial value. Like this. Now this is a signal. And so, we cannot directly  increment it. It will throw error. If I console log this, we can  see, this is a signal function. So, how can we access the value. We just need to call the function. Now, we can see the value. And so, you can ask me, to  fix this can we do like this. No, we cannot assign a  value to a signal like this. There are few inbuilt functions available  to change the value of a signal. If we need to just replace the  value, we can use the set function. Let me set the value as 7. Now, if I click the button, we can  see it is getting changed to 7. Similarly, instead of 7, if I give this dot count  plus one, we can see this is getting incremented. But according to angular documentation, we  have to use set to update a simple value. And, we can use update method to update a new  value of a signal depends on its previous value. So, let me use the update method. Update method accepts a function. Like this. We can see this is working as expected. So, we have seen how we can update simple   values like a number. Let me show  you how we can update an array. Let me create a new signal having an  array as initial value. Initially,   I have kept two elements in the array. Now, I need to add another array. For this use case, we have another method, mutate. Mutate accepts a function which  takes all the values as parameter   and we can use the push method to add the  value and return all values. Like this. Now, if I put a console log, we  can see when I click the button,   we can see the new value  has been added in the array. But, this will work only in angular 16.  This has been dropped in angular 17. Instead of mutate, we can use update itself. But, when we use update function, instead of push,  we need to use the spread operator. Like this. We can see, this is working. So, we have learnt about writable signals. Let's move to computed signals. Computed signals are essentially  values derived from other signals. Computed signals are read only. We cannot  directly set the values of computed signals. Let me show you an example. Let me create a new signal, length. And, another signal, breadth. Now, let me create a computed signal, area.  Which is going to be the product of both. Let me show this area instead of count. We can see, 800. Now, when I click the button, let me update  one of the signals. May be length to 30. Now, if I click the button, we can see 1200. That means, when one of the signals is changed,   the computed signals is  automatically getting recalculated. That is about computed signals. We have one more concepts, effects. Signals are useful because they can notify  interested consumers when they change. And, an effect is an operation that runs  whenever one or more signal values change. Effects always run at least once. Like computed signals, effects keep  track of their dependencies dynamically. Let me show you how to create an effect. The good place to create an  effect is inside a constructor,   because effect function  requires an injection context. So, inside constructor, let me create an effect.  Effect accepts a function. Inside that function,   let me put a console log. Inside the  console log, let me use the count signal. Similarly, let me create another effect.  Now, let me use the colors signal. First, let me update only the count signal. Now, if I click the button, we can see  only the first effect is triggered. Let me comment this and update the colors signal. Now, we can see the second  effect is getting triggered. If I update both, we can see both  the effects will be triggered. If I just refresh the browser, we can see  these, because effect always run at least once. Effects will be used in many places. For example,   if you want to log something when a  signal is changed, we can use effects. If we need to update the local storage when  a signal is changed, we can use effects. But, there are certain things we need to consider   while using effects. We should not  update any signals inside effects,   because it may trigger infinite circular updates  and trigger unnecessary change detection cycles. To avoid this, setting signals is  disallowed by default in effects.   But we can enable that if it is really necessary. I will show you an use case shortly to  enable setting signals inside effects. Ok. We have learnt the important  concept in Signals. But,   do you understand why we  really need to use signals? Let me explain that also using a simple example. Let me create a variable a equals to  10 and another variable b equals to 20. Now, let me create another variable  c, which is equal to a plus b. And, in ngOnInit, let me console log this c. After that, let me change the value of a to 50. Now, let me console log this c again. And so, we can see 30 and 30. This is because, the value of c was  calculated before the value of a was changed. And so, c has no idea whether the  value of a has been changed or not. There is no reactivity. Let me implement the same using signals. Ok, now we can see, the first console log is  printing 30 and the second one is printing 70,   because now the signal c has been notified that  one of the dependent signals has been changed. And so, the value has been recalculated. This has reactivity. Hope you understood the use of signals. Now, let's see how signals are  useful in a real time application. I have created this add to cart application. Here, we can add fruits and  vegetables to the cart. And   we can click this cart to see  the items in the cart. Also,   I have implemented a mechanism to show the  points to be earned based on the cart value. I have added only limited features. For  example, I have added logic only to add to   cart. There is no feature implemented to reduce  the quantities or to remove the item from cart. The reason is I want you to focus on  the signals implementation. Adding   too many features may deviate us from the concept. Also, I have not implemented a perfect add to cart  design. For example, I have added some subjects,   some @Input and @Output, etc. Definitely,  we can follow a better design to avoid this.   But I have implemented this in such a way  that I can explain you the signals concept. Ok, first let me show you this  feature. When we click this cart,   this cart is getting opened and on clicking  this close button, we can close this cart. Let me explain how I have implemented this. In cart service, I have created a behavior  subject which is having an initial value as false. In header component, on clicking this  cart icon I am calling a function,   inside that I am changing the  value of the subject to true. Similarly, in the cart component, on clicking this  close button, I am changing the value to false. And in app component, I have injected the cart  service and in the template, I have kept the cart. And, I am toggling a class named open,  based on the behavior subject value. I have used the async pipe to resolve the subject. And in css, you can see I have placed the cart in   fixed position away from the view  port and when the class is added,   I am moving the cart inside the view port.  I have also used a transition effect. Ok, now let's see how we can  use signals to simplify this. First, in the cart service, I don't  want the behavior subject. Instead   let me create a signal. Let me  keep the initial value as false. In the header component, let me remove this  and let me set the signal value as true. Similarly, let me set it as  false in the cart component. Finally, in the app component,   I don't want the async pipe. I can  simply get the value of the signal. That's it. We can see it is working like before. But now,   we don't need the behavior subject  to notify all the components. Ok. In the cart service, we can  see I have two more subjects. The refresh cart subject is to notify  the cart component whenever I add an   item to cart. So that the cart will be refreshed. You can see, in add item component,  once an item is added to cart,   I am calling the next function of this subject. And in the cart component ngOnInit,  I am subscribing to this subject and   whenever there is a new value, I am  calling the refresh cart function. In this refresh cart function only, I am  having the logic to calculate total price,   total quantities and the final  cart to display in the cart popup. You can see, if the item is already  in the cart I am just increasing   the quantity or otherwise I am  adding the item into the cart. Also, I am maintaining the total value of the cart   in the cart service. So that I can  use that to calculate the points. So, after the total value  is set in the cart service,   I am triggering another subject refresh header. In the header component, I have  subscribed to this refresh header   subject and whenever a new value is received,  I am calling the refresh points function. In this function, I have the  logic to calculate the points. Now, let's see how we can change  this implementation and use signals. So in cart service, let me  delete these 2 subjects. I   don't want them because I am going to use signals. And, let me change this cart  and this totalValue to signals. In add item component, we don't want  to notify now. So, let me remove that. And in the cart component, we don't want  to subscribe. Let me remove that also. Similarly in the cart component, we don't want  to notify. And so, let me remove this line. And in the header component,   we don't want to subscribe to the  subject. Let me remove that as well. As we have changed these cart  and total value to signals,   in the cart component we need to change this. Now, we are getting an error.  This is because of typescript. We can fix this by adding a type in the  signal declaration in the cart service. And then, here we need to use the  set function to set the value. Ok, in the header component  we don't need this function. Instead, let's create this points as a  computed signal, so that whenever the   total value signal is changed, this  will be automatically recalculated. And, when we change this to a signal, we  need to change in the template as well. This cart is also a signal now, and  so we need to change this as well. To add an item into an array,  we can use the mutate function.   Like this. We can see one more error. We need to change this as well. Ok. No more errors. Let's test this. When I add some items to cart, we can  see the cart count is getting changed. But, if I open the cart, we cannot see any items. Also, this points is not getting updated. What could be the reason? The problem is in the cart component. Earlier, we used the subject to trigger  this refresh cart function. But now,   this is not at all called. So how can we trigger this function. Here comes the use of effects. Let me create an effect inside the  constructor and let me call this function. That means, whenever my cart signal is changed,  I need to call this refresh cart function. But if I refresh this page, we can see an error.   We cannot set a signal value inside  an effect or inside computed signal. We can see we are setting the total  value signal here. This is not allowed. But we know, this is not going to trigger any   infinite change detection  cycles or impact anything. So for this scenario, we can use  the create effect options. Where   we can set allow signal writes to true. Like this. Let's test this once. It is working as expected. Hope you understood how we can make  use of signals in our applications. If you like this video,  please hit the like button,   subscribe to this channel and share this  video with your friends and colleagues. Post your valuable comments  in the comments section. I will be back with another  interesting concept soon. Thank you. Bye.
Info
Channel: Web Tech Talk
Views: 4,800
Rating: undefined out of 5
Keywords: angular tutorial, angular signals, angular, angular signals tutorial, angular signals example, angular tutorials, signals in angular, complete angular course, signals angular tutorial, signals tutorial angular, signals, angular signal, signals angular, angular 16 signals, signals for data sharing in angular, signals example angular, angular 4 tutorial, signal tutorial, signals angular app, angular signals for beginners, learn angular signals, angular signals explained
Id: n1a2eQ0Zyls
Channel Id: undefined
Length: 15min 21sec (921 seconds)
Published: Wed May 15 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.