Manage State with Angular Signals

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey one key use of signals is to manage state in our angular applications before we jump into a demo let's clarify the concept of State state is basically data that we retain in our code often in variables defined as class properties we Define state in our components to keep component level data such as the user's desired sort order or current selected item we Define State and our services to retain data used throughout the application such as the list of vehicles for sale or the content of the user's shopping cart in some cases we need to support crud operations on that data what's crud that's create read update and delete so the user can create a cart update it that is ADD items to the cart or adjust the quantity and delete items from the cart in this video we'll do just that if you are new to angular V16 signals check out my introductory signals video you can find the link to that video in the upper right corner now or in the this video's notes let's get started here is my Star Wars vehicle sales application in a prior video linked above we modified the cart item component to create signals these signals manage the state for this component we have the valid quantities which we use to bind to a quantity drop down here we manage the cart item itself and here we use a computed signal to calculate the extended price which is the selected quantity times the cost of the item in this video we'll work on the cart service currently we're managing the cart State using observables will change all of this code to use signals instead before we start modifying the code let's take a quick look at how the cart functionality works I'll run the application and here is the application in action click on vehicle list and we see our list of vehicles select a vehicle and the vehicle detail appears click on add to cart to add the selected vehicle to the cart notice that the menu shows the number of items in the cart select a second vehicle and click on add to cart to add another vehicle to the cart click on the cart menu and we see the items in our cart along with the cart total dropping down the quantity we see the list from our quantity array signal notice that when we select a new quantity the extended price shown here is the cost reacts to the change and recalculates as does our car totals and if we delete one of the items from our cart the cart totals recalculate now let's see how to manage our state using signals here is the cart service notice that it's implemented using rxjs and observables many of us use observables to manage state in our services this is a bit challenging because observables emit data and don't retain that data by default this is different from signals that do hold on to that data value if we want to perform crud operations with observables we need to either use a behavior subject which retains the last emitted item or use something like the scan operator which retains and provides the last emitted item and lets us modify that item before emitting it again we need to find an action to tell the observable whether we are adding an item to the cart updating the item quantity or deleting an item from the cart we then respond to that action modifying the cart when the cart items array emits we recalculate the subtotal and if that subtotal emits we recalculate the delivery fee tax and total price all using observables if you didn't follow all of that don't worry we're going to delete all of this code let's start with a cart which is an array of cart items will create a signal card items equal signal and we'll add the import for the signal we'll start with an empty array as the initial value hovering over card items we see that it is of type never array that's not what we want let's strongly type the signal using the generic argument cart item array and let's add a comment we no longer need this subject because the cart item signal will provide notification when the cart changes and we don't need this card items observable so I'll delete that as well but what about this subtotal observable any idea how to implement that with signals if you set a computed signal you are correct let's create a computed signal subtotal equal computed and we'll add the import for computed for the computed expression we'll copy the code from our observable Pipeline and paste it into our computed expression I'll do a little reformatting then change items to our cart item signal don't forget the parentheses to read the signal this code reads the card items array signal then uses the array reduce method that method processes each array element in order passing in the return value from the calculation on the preceding element a in this example with the current element B in this example the first time that this method executes there is no value from the prior calculation so at the end here we provide an initial value of zero now we can delete the subtotal observable next we'll create a signal for the delivery fee and yep we'll do that with a computed signal as well delivery fee equal computed for the computed expression we'll read the subtotal signal if that value is less than a hundred thousand credits the fee is 999 credits otherwise it's zero and we can delete this observable how about the tax another computed signal tax equal computed for the computed expression we'll copy the calculation from the observable pipeline paste it here and change T to instead read our subtotal signal and we no longer need this observable and lastly We'll add a computed signal for the price total price equals computed in our computed expression we read the subtotal signal and add that to the delivery phase signal and the tax signal then delete this observable that looks pretty straightforward and easy to read we have our cart which is an array of cart items we have the subtotal delivery fee tax and total price all as signals scrolling down but what about our crud operations adding to the cart removing items from the cart or updating the quantity in the cart instead of emitting into an observable to kick off a notification and recalculate like this code does will instead modify our signal the signal will automatically provide notification and all computed signals will recalculate let's start with the add to cart method here we create a cart item that includes the user selected vehicle and a default quantity of one and we provide an action of add we emit that value to our observable instead we'll now add the item to our cart items array signal we don't need to worry about an action because the signals will provide notification to make an internal change to a Signal's value without changing the Signal's identity use mutate mutate is useful for modifying the content of an array or changing object properties we'll call the cart item signals mutate method in the mutate expression we push a new card item with the selected vehicle and a default quantity of one now we can delete the code that calls next on the observable to remove an item from the card we want to use the array filter method to filter out the deleted cart item however the filter method doesn't update the existing array rather it creates a new array so we'll use the update method to modify the value of the signal based on the current value of that signal in the update expression we use the array filter method and only return the array items that don't have the same vehicle name as the deleted item effectively creating a new array with all but the deleted item normally we would use IDs instead of names here but this particular data has no IDs we no longer need this code so let's delete it lastly to update the quantity of the item in the cart we use the array map method the map method processes each item in the array to find and update the appropriate cart item like the array filter method the map method creates a new array so we'll again call the update method of the signal reference the signal call its update method in the update expression use the card items array map method for each item in the cart if the item has the vehicle name that matches the updated item we replace the item with the new item and quantity otherwise we return the original item again normally we would use IDs instead of the name now we can delete the code that uses the subject since we are handling the changes to our cart items array signal directly in these methods we don't need this additional method that modifies the cart so we can delete it scrolling up let's delete our unused Imports our service now exposes several signals that our components can use to access our state so next we need to access these signals from our components I'll open the card total component TS file will change each of these observables to a signal instead our card items dollar becomes card items the subtotal dollar becomes subtotal the delivery fee dollar is now delivery fee tax dollar is tax and total price dollar is total price then we bind to these signals in the template which in this case is in the cart total component HTML file here at the top instead of the async pipe will bind to the signal don't forget the opening and closing parentheses to read the signal value and since the signal always has a value we don't need the question mark here next we change each of our computed signals subtotal here delivery fee which is referenced in this ngf here this binding and this ngf down here then tax and total price our template now binds to our signals but we're not quite finished our cart state is used in a few more places I'll open the cart list component.ts file we'll change the reference to our card items observable to our cart item signal and change the binding to read that signal lastly recall that our menu displayed the quantity of items in our cart so I'll open the app.component.ts file here we calculate the quantity how do we change that to a signal yep it's another computed signal we'll create a cart count computed signal add the import and then the computed expression we read the signal from the service we then use the arrays reduce method to total up the quantity of items in the cart then we can delete this observable and delete the unused Imports let's change the template as well open the app component.html file here we display the car quantity we'll change it to use the signal instead of the async pipe and let's add an ngif so we only display the quantity if the value is set to a non-zero number that should be it let's give it a try I'll bring up the application click vehicle list to see the list of vehicles select a vehicle and click add to cart notice that our cart quantity is updated select another vehicle and click on add to cart and again our quantity is updated click on cart and we see our cart change the quantity on one of the items and all of our computed signals recalculate nice next let's try out the delete click X to delete one of the items from the cart and our totals adjust accordingly cool going back to the cart service by using signals to manage our state we've simplified our code making it easier to read modify and maintain if you have any questions or would like to see a video on another signal topic please post those questions or suggestions in the comments thanks for watching and don't forget to like And subscribe
Info
Channel: Deborah Kurata
Views: 3,132
Rating: undefined out of 5
Keywords: Angular, signals, Best practices, Angular signals, Signals in Angular, Demo, Signal Tutorial, Angular 16, RxJS, RxJS and Signals, Signals and RxJS, Signal vs BehaviorSubject, CRUD, state management, state management in angular
Id: 04avEeicarQ
Channel Id: undefined
Length: 14min 23sec (863 seconds)
Published: Wed Apr 26 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.