in my humble opinion, this lady must be the best explainer i've ever seen, and signal is a game changer in angular universe, i love it. you have a new subscriber, i follow you long time ago and i think you do a awesome job
I follow you since I took your courses on Pluralsight! , love your teaching style. So glad I found your channel so I can keep learning from you here! Please keep it up!
I also have been following you since your Pluralsight days and have watched and studied your courses several times. The clarity and real world analogies in your courses is unmatched.
Nice refactoring. Well done! Btw. you can press "shift + cmd + o" execute the action "Optimize imports". This will remove the unused ones. And instead of clicking the little bulb for importing, you can press "cmd + ." Just saying...
This is absolutely revolutionary... a complete game changer! I have been waiting for anyone to create a replacement for the way we have been managing state in Angular. Absolutely nobody liked the way it was being done before. I am definitely replacing all of my traditional state code with signals. Thanks for another great video.
I've been sharing these Signals videos with my team, and they are really enjoying them. We are really excited to see where we can simplify some of our RxJS stateful services with Signals. Thank you!
Greetings from Cuba. Teacher does not know how glad I am to see that you have content here too. I have learned so much with you that the truth would not have how to repay you. The work you do is incredible and the excellent teacher you are. I am very sorry for my English. I have helped myself with the google translator :). Wow, you are the best, I would not have wanted to learn Angular from anyone other than you. I've seen every course of yours on pluralsight and often come back to see if you've updated any. Thank you very much for your excellent work God bless you always
Signals bring a more straight forward way to manage state in my opinion, and actually with less code and concepts to grasp, i'm really happy with this new feature and can't wait to use it in production when the API will be stable.
really understand more about SIGNAL +RXJS real usage... while watching this i feel we can manage state in app with using signal instead of using NGRX it makes simple minimal fast code, love it 🤟 Thank you very much Deborah
Hi Deborah, excellent explanation of signals - the best I have come across so far. You and Julie Lerman are two of my favorite presenters. So clear yet thorough - how do you do it! I miss the "yay"s though 😁
Loving these videos on signals, I especially like that most of the time they come with real world examples and not only snippets of code! Thank you for doing such an amazing job at spreading information
I am fan of your video from pluralsight, great content and easy explanation, it helps me to transition from 9lac package to 20lac package in software industry. Keep it up 🎉
You have the knowledge, art to teach, even your way of talking is pedagogical, I am interested to buy your courses if you have paid ones. Thanks with just 2 vidoes I am production ready with Signals and on the way I finally understood the use of services.
Wow, that's create to hear. Thank you! I have some "paid" courses on Pluralsight: app.pluralsight.com/profile/author/deborah-kurata I also have several free courses on RUclips, such as: "Gentle Introduction to Git and GitHub" "Gentle Introduction to JavaScript"
Excellent video, but in light of the recent Angular PR when signals were marked as stable (#51821), it probably wouldn't hurt to add a comment in the description of this video to note that the mutate() method is now removed and the Angular team has indicated users should replace that with update() calls instead. Otherwise, everything is spot on!
Thank you! NgRx will still be useful when an application has complex state management. And NgRx has already begun to embrace signals. Check out a summary here: dev.to/this-is-angular/signals-what-this-means-for-ngrx-eho
Yes, but with more features. 😊 For example, changing a signal referenced in a computed signal schedules change detection so that the UI will automatically update.
The signal and computed are treated like any other variable ... they are garbage collected after the component or service is destroyed. For effects, they are also automatically destroyed when the "enclosing context" (such as the component or service) is destroyed. There is more on this here: angular.io/guide/signals#destroying-effects
Another GREAT tutorial! Btw, what kind of vscode extrensions do You have to debug code? Could You share configuration? Actually Im struggling with it, switched to chrome source tab..
I don't have any vscode extension for debugging the code. Rather, it's part of Angular's configuration. If you do an ng new with the latest version of the CLI, it generates the configuration you need to debug within vscode. Let me know if you need more information on this.
Thank you for the great explanation and example. I am wondering if there are any downsides to using signals in the template that were not explained. Generally, it is known that using function calls in the template can cause performance issues. This is because if Angular detects an expression in the template that includes a function call, it needs to recalculate the function during every change detection cycle. I would like to know how this works in the case of signals. Is there any difference? Is it pure in some way, meaning that the signal function is not recalculated during every change detection cycle? Thanks! Kind regards, Radovan.
Thank you! There are no downsides of using signals. Signals are zero-argument functions, basically getters. When executed, all they do is return the current value of the signal. They have no side effects to worry about. And they don't execute any other code. So it's no different really then reading a property value. The performance gets even better if you bind only to signals and turn on OnPush change detection. Does that answer your question?
Hey Deborah, would you be able to do a video on Image Optimization for Angular projects? I'm having so much trouble with ngSrc getting it's value from a signal. Anytime I refresh the page, everything get's updated on the page, the images show, but ngSrc says there are empty strings and fails my application?
I got a question: Say you were in an environment where your app was being maintained by a large team, and you wanted to protect your cartItems signal from being modified outside the service unwittingly by one of your developers. How would you go about making it read only? One method I have seen would be to define it over two lines by adding a private identifier to cartItems, update all calls within the service to #cartItems, then make a new cartItems computed signal to be read from outside the service, like this: #cartItems = signal([]) cartItems = computed(this.#cartItems) It works, but I don't really like the way it looks in the code. Is there a better way to do this? perhaps on one line?
I've given this quite a bit of thought and it seems that if you need to maintain two signals: - A read-only one available to consumers. - A writeable signal for use within the service Then you'll need to create two signals, so two lines of code. If building an app maintained by a large team, a better answer may be to use NgRx or some other state management library that works well with signals. See this for more information on the latest version of NgRx that works with signals: dev.to/ngrx/announcing-ngrx-v16-integration-with-angular-signals-functional-effects-standalone-schematics-and-more-5gk6 Hope that helps!
How you save depends on your requirements. If you want to "auto save" after each operation, you could add the post, put, or delete directly in the add/update/delete methods. If you want the user to control the save via a save button, then you would call a save method in the service to perform the save. Depending on your backend, you could pass the entire array back to the backend. Or you may need to add an "action" to the data array so that on the save the code can loop through the array and know which elements are new, which are updated, and which are marked for deletion. Does that answer the question?
@@deborah_kurata So for Auto Saving when User add, update or delete Cart , I can subscribe to http post put and delete in service method add/update/delete and then once response comes back from server we can update cart Item signal accordingly.
Yes, that should work. I need to work on a CRUD example that does this. Most of the "open source" end points (like this starwars one) don't allow updates. So I'll have to figure out where/how to set up an endpoint where I can do post/put/delete. Or maybe try Angular's fake Web API?
Thank you! And Yes! You'd still use RxJS for the async save operation. How you save depends on your requirements. If you want to "auto save" after each operation, you could add the post, put, or delete directly in the add/update/delete methods. If you want the user to control the save via a save button, then you would call a save method in the service to perform the save. Depending on your backend, you could pass the entire array back to the backend. Or you may need to add an "action" to the data array so that on the save the code can loop through the array and know which elements are new, which are updated, and which are marked for deletion.
@@deborah_kurata how to convert this into signal productsWithCategory$ = combineLatest( [this.products$, this.productCategoryService.productCategories$] ).pipe( map(([products, categories]: [Product[], ProductCategory[]]) => products.map( p => ({ ...p, category: categories.find(c => p.categoryId === c.id).name } as Product) //
Well explained! Question: How would you do CRUD with signals for real, all the way? For example - if a list of items is loaded from an http call (as it usually is), then the signal created from that call's observable is read only, i.e. Signal and not WritableSignal.
Thank you! I've been using this: // Create a writable signal. // Use an effect to react to the userId changes // Get the data using the parameter // Use takeUntilDestroyed() to ensure the Observable is destroyed // when the component is destroyed // Subscribe to that Observable // In the Observer, set the writable signal. userTasks = signal([]); // Writable signal destroyRef = inject(DestroyRef); // Current "context" (this component) tasksEffect = effect(() => this.http.get(this.todoUrl + this.userService.selectedUserId()).pipe( takeUntilDestroyed(this.destroyRef), catchError(() => of([] as ToDo[])) ).subscribe( tasks => this.userTasks.set(tasks) ) ); I have the full code here: github.com/DeborahK/Angular-Signals/tree/main/taskList-end
@@deborah_kurata Thanks! Brings however a couple of more questions: 1. Does the effect written as such automatically convert the observable to a signal? If not - why use an effect if there's no signal to react to? 2. Seems to somewhat go against your recommendation "An effect should not change the value of any signals. If you need to change a signal based on a change to a dependent signal, use a computed signal instead."
@@peperudpeperudski1911 1. No. Looking at the code above, it's reacting to the `selectedUserId()` signal. (I should have clarified that my example was for an http request that required a query parameter.) 2. Yes. This should *not* be the way to do it. There is the expectation that the Angular team will add a feature to create a writable signal from an Http request at some point. (Signals are only in developer preview and are in no way "done".) And technically, we are not updating the signal from the effect. We are updating the signal from the Observable callback function. 🙂 Also, we could not use a computed signal in this case because the return type would be wrong. (I write up quite a bit about that in the above referenced code.)
@@peperudpeperudski1911 Here is a better example for creating a writable signal from an http request with no parameters. (It does not require an effect) users = signal([]); private sub = this.http.get(this.userUrl).pipe( tap(data => this.users.set(data)), takeUntilDestroyed(), catchError(() => of([] as User[])) ).subscribe();
Hi Deborah, do you have a video that shows how you created your SW Vehicles from scratch? I have downloaded your code from Git Hub, but I am interested in learning your thought process.
Yes, but because it's a course, I couldn't do "Star Wars" so it's just "products". :-) You can find it here: www.pluralsight.com/library/courses/rxjs-angular-signals-fundamentals This site requires a membership, but you can sign up for a free trial to watch the course.
congratulations on a fantastic tutorial. It is, however, my feeling that signals are not meant to be used on services but rather as a bridge between the service and the UI. In services, sometimes you need to respond to change in the signal value. This is done with the "effect" function, but the problem is that you cannot change any writeable signals in the effect code. So if you want to start an asnycronous operation when a signal changes (for example load details when the currently selected customer id changes) and change an "isLoading" signal from false to true before you start, you will get an exception. It may not seem like a big deal, but architectually this can be a nightmare. You can never call any method in any service inside an effect, because you can never know if the method causes a signal to change. My conclusion is that you should continue to use RxJS in services, and use signals only on the presentation layer, to combine computed values, and prepair them for binding into the UI. Would love to hear what you think about it 🙂
Glad you liked the tutorial. Could you take a look at my more recent video, as it relates to the above, and let me know what you think? ruclips.net/video/nXJFhZdbWzw/видео.html
Would you please mind create a video for angular lifecycle after signal? I guess that some new life cycles are created and some are useless if using signal.
The new lifecycle hooks are not in the v16 release. AKAIK, the Angular team has not completed their plans/implementation on lifecycles. (And recently decided to keep more of the original lifecycle hooks than originally thought.) I will definitely do a video on them once they are more stable.
Signals are basically a container for a variable, so they are destroyed just like any other variable (array, object, number, etc). The feature that you may want to destroy is an effect. See the docs for more information on that. angular.io/guide/signals#destroying-effects
It's hard to tell. Could you create a stackoverflow issue with the important pieces of code? If so, please reply with the stackoverflow link and I'll take a look.
I have a page that gets the data from http observeble and i made it signals by toSignal method but after CRUD like add new data or delete i am not able to update the data because i can not mutate the tosignal array apperntly it is read only , how to do that?
There are several different ways to do this ... none of which are great. The hope is that more signal features will be coming to make this easier. Here are some options, which you can find here: github.com/DeborahK/Angular-Signals/tree/main/taskList-end // Option 1: // Create a writable signal. // Use an effect to react to the userId changes // Get the data using the parameter // Use takeUntilDestroyed() to ensure the Observable is destroyed // when the component is destroyed // Subscribe to that Observable // In the Observer, set the writable signal. userTasks = signal([]); // Writable signal destroyRef = inject(DestroyRef); // Current "context" (this component) tasksEffect = effect(() => this.http.get(this.todoUrl + this.userService.selectedUserId()).pipe( takeUntilDestroyed(this.destroyRef), catchError(() => of([] as ToDo[])) ).subscribe( tasks => this.userTasks.set(tasks) ) ); // Option 2: // Create a writable signal. // Use an effect to react to the userId changes // Get the data using the parameter // Use tap to set the writable signal // Use takeUntilDestroyed() to ensure the Observable is destroyed // when the component is destroyed // Subscribe to that Observable userTasks2 = signal([]); // Writable signal destroyRef2 = inject(DestroyRef); // Current "context" (this component) tasksEffect2= effect(() => this.http.get(this.todoUrl + this.userService.selectedUserId()).pipe( tap(tasks => this.userTasks2.set(tasks)), takeUntilDestroyed(this.destroyRef2), catchError(() => of([] as ToDo[])) ).subscribe() ); // Option 3: // Create a writable signal. // Create an Observable from the selectedUserId signal // React to emissions, piping the userId through an Observable pipeline // Use switchMap to get the data // Use toSignal to automatically subscribe and unsubscribe userTasks = signal([]); // Writable signal private userTasks$ = toObservable(this.userService.selectedUserId).pipe( switchMap(userId => this.http.get(this.todoUrl + userId).pipe( tap(tasks => this.userTasks.set(tasks)) )), catchError(() => of([] as ToDo[])) // on any error, just return an empty array ); // This signal is not used // It's only here to automatically handle the subscribe and unsubscribe. readOnlyUserTasks = toSignal(this.userTasks$, { initialValue: [] as ToDo[] });
Thank you for your feedback. The "why" is important indeed. A follow up question: "why" which in this particular video? Why to use signals? I mentioned about 1:07 that the intro to signals, including the why, is in a separate video aptly entitled: "Angular Signals: What, Why, and How?" I didn't repeat that content in this video. Or do you mean "why" to use state?
I am using this video as my template for migrating my project from observables to signals. // To react to events when the is closed | sucess | reject | cancel private uaSelectedActionSubject = new BehaviorSubject(''); uaSelectedActionMessage$ = this.uaSelectedActionSubject.asObservable(); // Replace the uaAction with uaSelectedActionMessage$ uaAction = signal('');
in my humble opinion, this lady must be the best explainer i've ever seen, and signal is a game changer in angular universe, i love it. you have a new subscriber, i follow you long time ago and i think you do a awesome job
Thank you so much for the very kind words!
I follow you since I took your courses on Pluralsight! , love your teaching style. So glad I found your channel so I can keep learning from you here! Please keep it up!
Thank you! 🙏
I am on the same boat, love her teaching style
Same here😅..
I also have been following you since your Pluralsight days and have watched and studied your courses several times. The clarity and real world analogies in your courses is unmatched.
Thank you so much!
If you are still on Pluralsight, I just published a new course "RxJS and Angular Signals Fundamentals".
Nice refactoring. Well done! Btw. you can press "shift + cmd + o" execute the action "Optimize imports". This will remove the unused ones. And instead of clicking the little bulb for importing, you can press "cmd + ." Just saying...
Thank you! And thanks for the tips.
This is absolutely revolutionary... a complete game changer! I have been waiting for anyone to create a replacement for the way we have been managing state in Angular. Absolutely nobody liked the way it was being done before. I am definitely replacing all of my traditional state code with signals. Thanks for another great video.
Thank you. Glad it was helpful!
You are an excellent teacher. The material is relevant, clear and crisp. I also enjoy your enthusiastic voice and your pace of speaking.
Thank you so much for the very kind words! 🙏
So thankful for this channel and you, Deborah!
That is so very kind of you to say. Thank you!
I've been sharing these Signals videos with my team, and they are really enjoying them. We are really excited to see where we can simplify some of our RxJS stateful services with Signals. Thank you!
Glad to hear they have been useful. Thank you!
Greetings from Cuba. Teacher does not know how glad I am to see that you have content here too. I have learned so much with you that the truth would not have how to repay you. The work you do is incredible and the excellent teacher you are. I am very sorry for my English. I have helped myself with the google translator :). Wow, you are the best, I would not have wanted to learn Angular from anyone other than you. I've seen every course of yours on pluralsight and often come back to see if you've updated any. Thank you very much for your excellent work God bless you always
Thank you so very much for the very kind words! It is so wonderful to know that my content has been useful.
All the best to you!
You are AWESOME. An excellent teacher who covers all the bases. I’m highly impressed!
Wow, thank you! ☺
Signals bring a more straight forward way to manage state in my opinion, and actually with less code and concepts to grasp, i'm really happy with this new feature and can't wait to use it in production when the API will be stable.
Agreed! Thanks for your post!
really understand more about SIGNAL +RXJS real usage... while watching this i feel we can manage state in app with using signal instead of using NGRX
it makes simple minimal fast code, love it 🤟
Thank you very much Deborah
Thank you!
Also, NgRx now has a signal store that is great to use.
Very nicely explained! I love Deborah's videos since I first found them in Pluralsight
Thank you! 😊
This is both up to date, refreshing and concise to watch. Thanks
Thank you!
Deborah is the coding instructor GOAT!
Wow! Thank you so much!
Learned so much from one single signal video. Thank you 🙏
Great to hear! Thanks!
Excellent tutorial. Thanks for all the time and effort that you take to do this for us. You are the best. Wow!
That is very kind of you to say. Thank you! 😊
Amazing content, Thanks Deborah Kurata for the amazing videos.
Glad you like them! Thank you!
Hi Deborah, excellent explanation of signals - the best I have come across so far. You and Julie Lerman are two of my favorite presenters. So clear yet thorough - how do you do it! I miss the "yay"s though 😁
That is very kind of you to say. Thank you so much! 😊
I'll see if I can fit a "yay" or two in the next one. LOL.
Glad i found this channel...thanks Deborah
Great to see you here! ☺ Thank you!
Loving these videos on signals, I especially like that most of the time they come with real world examples and not only snippets of code! Thank you for doing such an amazing job at spreading information
Great to hear they are useful! Thank you!
I am fan of your video from pluralsight, great content and easy explanation, it helps me to transition from 9lac package to 20lac package in software industry. Keep it up 🎉
Thank you! 🙏
Found the best and simple explanation for the signals. You got yourself a new subscriber 👍🏻
Excellent! Thank you! 🙏
@@deborah_kurata are you planing for any backend series in future?
I am starting to build out some C# content. Is there something specific you are looking for?
You have the knowledge, art to teach, even your way of talking is pedagogical, I am interested to buy your courses if you have paid ones. Thanks with just 2 vidoes I am production ready with Signals and on the way I finally understood the use of services.
Wow, that's create to hear. Thank you! I have some "paid" courses on Pluralsight: app.pluralsight.com/profile/author/deborah-kurata
I also have several free courses on RUclips, such as:
"Gentle Introduction to Git and GitHub"
"Gentle Introduction to JavaScript"
@@deborah_kuratathanks I will have a look at them
I thought a similar way to implement signals like a store . Thanks for all Deborah.
So much thanks for your great sharing, that helps people a lot.
Glad it was helpful! Thank you!
Excellent video, but in light of the recent Angular PR when signals were marked as stable (#51821), it probably wouldn't hurt to add a comment in the description of this video to note that the mutate() method is now removed and the Angular team has indicated users should replace that with update() calls instead. Otherwise, everything is spot on!
Great idea!
I really wish RUclips allowed updates to existing videos ... to at least put in a callout or something ... but no. 😑
superb explanation in simple way to manage state.
Thank you! 🙏
Kurata I love your tutorials! Thnxz!
Glad you like them! Thanks!
Thank you. Waiting for a new content about signals
Have you see this one: ruclips.net/video/nXJFhZdbWzw/видео.html
Wow, it was exactly what I was looking for. Appreciate such a good explanation ❤.
Do you think that this way of stage management will replace NgRx?
Thank you!
NgRx will still be useful when an application has complex state management. And NgRx has already begun to embrace signals. Check out a summary here: dev.to/this-is-angular/signals-what-this-means-for-ngrx-eho
@@deborah_kurata Thank youu!
Another nice example, thanks a lot again :) Keep it up please
Thank you! 🙏
Thanks a lot for this amazing tutorial. 👏👏👏
Glad it was helpful! Thank you!
thanks deborah..you're the best
Thank you! 🙏
Wow thanks for the courses about signals ! Could you please one day explain the angular universal concept? 🙏🏽
Thank you for the suggestion. I have not used Angular universal ... but I'll add it to the list to try out.
Excellent content, thanks for sharing!
Thank you! 🙏
Awesome awesome thank u! Would like to see practical uses of signal effects.
Great to hear! And great idea for a future video! Thanks!
Thanks for your efforts🎉
Thank you for watching!
Computed Signal feels like a C# getter. Is that right?
Yes, but with more features. 😊 For example, changing a signal referenced in a computed signal schedules change detection so that the UI will automatically update.
@@deborah_kurata Gotcha. Thank you.
Thanks very much for the video.. Can you pls explain what is the life cycle of the signal and computed. do they destroyed on component destroy
The signal and computed are treated like any other variable ... they are garbage collected after the component or service is destroyed.
For effects, they are also automatically destroyed when the "enclosing context" (such as the component or service) is destroyed. There is more on this here: angular.io/guide/signals#destroying-effects
Another GREAT tutorial! Btw, what kind of vscode extrensions do You have to debug code? Could You share configuration? Actually Im struggling with it, switched to chrome source tab..
I don't have any vscode extension for debugging the code. Rather, it's part of Angular's configuration.
If you do an ng new with the latest version of the CLI, it generates the configuration you need to debug within vscode.
Let me know if you need more information on this.
Very nicely explained, this works in Angular SSR application ?
Thank you.
SSR is something I haven't needed to do. So I don't know the answer to your question.
wow it simplifies very much
Yep! I have been enjoying working with signals.
Thank you for the great explanation and example. I am wondering if there are any downsides to using signals in the template that were not explained. Generally, it is known that using function calls in the template can cause performance issues. This is because if Angular detects an expression in the template that includes a function call, it needs to recalculate the function during every change detection cycle.
I would like to know how this works in the case of signals. Is there any difference? Is it pure in some way, meaning that the signal function is not recalculated during every change detection cycle?
Thanks!
Kind regards,
Radovan.
Thank you!
There are no downsides of using signals. Signals are zero-argument functions, basically getters. When executed, all they do is return the current value of the signal. They have no side effects to worry about. And they don't execute any other code. So it's no different really then reading a property value.
The performance gets even better if you bind only to signals and turn on OnPush change detection.
Does that answer your question?
Hey Deborah, would you be able to do a video on Image Optimization for Angular projects? I'm having so much trouble with ngSrc getting it's value from a signal. Anytime I refresh the page, everything get's updated on the page, the images show, but ngSrc says there are empty strings and fails my application?
I've had this on my list for quite a while. I should tackle it sometime soon. 😊
Really cool tut again
Thanks!
Amazing 😃 Thanks!
😊
I got a question: Say you were in an environment where your app was being maintained by a large team, and you wanted to protect your cartItems signal from being modified outside the service unwittingly by one of your developers. How would you go about making it read only?
One method I have seen would be to define it over two lines by adding a private identifier to cartItems, update all calls within the service to #cartItems, then make a new cartItems computed signal to be read from outside the service, like this:
#cartItems = signal([])
cartItems = computed(this.#cartItems)
It works, but I don't really like the way it looks in the code. Is there a better way to do this? perhaps on one line?
I've given this quite a bit of thought and it seems that if you need to maintain two signals:
- A read-only one available to consumers.
- A writeable signal for use within the service
Then you'll need to create two signals, so two lines of code.
If building an app maintained by a large team, a better answer may be to use NgRx or some other state management library that works well with signals.
See this for more information on the latest version of NgRx that works with signals: dev.to/ngrx/announcing-ngrx-v16-integration-with-angular-signals-functional-effects-standalone-schematics-and-more-5gk6
Hope that helps!
Wow... Simplifying complex topic .... Thanks.
What of i have to to post request on server or put and delete on server.. how the code will be affected
How you save depends on your requirements.
If you want to "auto save" after each operation, you could add the post, put, or delete directly in the add/update/delete methods.
If you want the user to control the save via a save button, then you would call a save method in the service to perform the save.
Depending on your backend, you could pass the entire array back to the backend. Or you may need to add an "action" to the data array so that on the save the code can loop through the array and know which elements are new, which are updated, and which are marked for deletion.
Does that answer the question?
@@deborah_kurata So for Auto Saving when User add, update or delete Cart , I can subscribe to http post put and delete in service method add/update/delete and then once response comes back from server we can update cart Item signal accordingly.
Yes, that should work. I need to work on a CRUD example that does this. Most of the "open source" end points (like this starwars one) don't allow updates. So I'll have to figure out where/how to set up an endpoint where I can do post/put/delete. Or maybe try Angular's fake Web API?
It would be great.. a fake angular webapi or json-server
This is Awesome ms Deborah, how about saving the data to the backend. Will that be the time to use rxjs?
Thank you! And Yes! You'd still use RxJS for the async save operation.
How you save depends on your requirements.
If you want to "auto save" after each operation, you could add the post, put, or delete directly in the add/update/delete methods.
If you want the user to control the save via a save button, then you would call a save method in the service to perform the save.
Depending on your backend, you could pass the entire array back to the backend. Or you may need to add an "action" to the data array so that on the save the code can loop through the array and know which elements are new, which are updated, and which are marked for deletion.
@@deborah_kurata how to convert this into signal productsWithCategory$ = combineLatest(
[this.products$,
this.productCategoryService.productCategories$]
).pipe(
map(([products, categories]: [Product[], ProductCategory[]]) =>
products.map(
p =>
({
...p,
category: categories.find(c =>
p.categoryId === c.id).name
} as Product) //
Well explained!
Question: How would you do CRUD with signals for real, all the way?
For example - if a list of items is loaded from an http call (as it usually is), then the signal created from that call's observable is read only, i.e. Signal and not WritableSignal.
Thank you!
I've been using this:
// Create a writable signal.
// Use an effect to react to the userId changes
// Get the data using the parameter
// Use takeUntilDestroyed() to ensure the Observable is destroyed
// when the component is destroyed
// Subscribe to that Observable
// In the Observer, set the writable signal.
userTasks = signal([]); // Writable signal
destroyRef = inject(DestroyRef); // Current "context" (this component)
tasksEffect = effect(() =>
this.http.get(this.todoUrl + this.userService.selectedUserId()).pipe(
takeUntilDestroyed(this.destroyRef),
catchError(() => of([] as ToDo[]))
).subscribe(
tasks => this.userTasks.set(tasks)
)
);
I have the full code here: github.com/DeborahK/Angular-Signals/tree/main/taskList-end
@@deborah_kurata Thanks! Brings however a couple of more questions:
1. Does the effect written as such automatically convert the observable to a signal? If not - why use an effect if there's no signal to react to?
2. Seems to somewhat go against your recommendation "An effect should not change the value of any signals. If you need to change a signal based on a change to a dependent signal, use a computed signal instead."
@@peperudpeperudski1911
1. No. Looking at the code above, it's reacting to the `selectedUserId()` signal. (I should have clarified that my example was for an http request that required a query parameter.)
2. Yes. This should *not* be the way to do it. There is the expectation that the Angular team will add a feature to create a writable signal from an Http request at some point. (Signals are only in developer preview and are in no way "done".)
And technically, we are not updating the signal from the effect. We are updating the signal from the Observable callback function. 🙂
Also, we could not use a computed signal in this case because the return type would be wrong. (I write up quite a bit about that in the above referenced code.)
@@peperudpeperudski1911 Here is a better example for creating a writable signal from an http request with no parameters. (It does not require an effect)
users = signal([]);
private sub = this.http.get(this.userUrl).pipe(
tap(data => this.users.set(data)),
takeUntilDestroyed(),
catchError(() => of([] as User[]))
).subscribe();
@@deborah_kurata re #1 Ah, yes. Missed that...not a hard thing to do with the "function like" syntax. Thanks!
Good explanation. Honestly, it's very difficult not to understand whatever you say lol
Thank you!
Hi Deborah, do you have a video that shows how you created your SW Vehicles from scratch? I have downloaded your code from Git Hub, but I am interested in learning your thought process.
Yes, but because it's a course, I couldn't do "Star Wars" so it's just "products". :-)
You can find it here: www.pluralsight.com/library/courses/rxjs-angular-signals-fundamentals
This site requires a membership, but you can sign up for a free trial to watch the course.
Found it. I do have a Pluralsight subscription. Thank you.
Thank for your 🎉
Thank you for watching!
congratulations on a fantastic tutorial. It is, however, my feeling that signals are not meant to be used on services but rather as a bridge between the service and the UI. In services, sometimes you need to respond to change in the signal value. This is done with the "effect" function, but the problem is that you cannot change any writeable signals in the effect code. So if you want to start an asnycronous operation when a signal changes (for example load details when the currently selected customer id changes) and change an "isLoading" signal from false to true before you start, you will get an exception.
It may not seem like a big deal, but architectually this can be a nightmare. You can never call any method in any service inside an effect, because you can never know if the method causes a signal to change.
My conclusion is that you should continue to use RxJS in services, and use signals only on the presentation layer, to combine computed values, and prepair them for binding into the UI.
Would love to hear what you think about it 🙂
Glad you liked the tutorial.
Could you take a look at my more recent video, as it relates to the above, and let me know what you think?
ruclips.net/video/nXJFhZdbWzw/видео.html
Would you please mind create a video for angular lifecycle after signal? I guess that some new life cycles are created and some are useless if using signal.
The new lifecycle hooks are not in the v16 release. AKAIK, the Angular team has not completed their plans/implementation on lifecycles. (And recently decided to keep more of the original lifecycle hooks than originally thought.)
I will definitely do a video on them once they are more stable.
Is the unit test environment ready for testing signals?
Afaik, the Angular team has not yet defined testing strategies for signals.
Do we need to unsubscribe the signals if we don't need them or it automatically removed his reference?
Signals are basically a container for a variable, so they are destroyed just like any other variable (array, object, number, etc).
The feature that you may want to destroy is an effect. See the docs for more information on that. angular.io/guide/signals#destroying-effects
When I reload or navigate to a new route the data is not up to date, what could be the issue?
It's hard to tell. Could you create a stackoverflow issue with the important pieces of code? If so, please reply with the stackoverflow link and I'll take a look.
I have a page that gets the data from http observeble and i made it signals by toSignal method but after CRUD like add new data or delete i am not able to update the data because i can not mutate the tosignal array apperntly it is read only , how to do that?
There are several different ways to do this ... none of which are great. The hope is that more signal features will be coming to make this easier.
Here are some options, which you can find here: github.com/DeborahK/Angular-Signals/tree/main/taskList-end
// Option 1:
// Create a writable signal.
// Use an effect to react to the userId changes
// Get the data using the parameter
// Use takeUntilDestroyed() to ensure the Observable is destroyed
// when the component is destroyed
// Subscribe to that Observable
// In the Observer, set the writable signal.
userTasks = signal([]); // Writable signal
destroyRef = inject(DestroyRef); // Current "context" (this component)
tasksEffect = effect(() =>
this.http.get(this.todoUrl + this.userService.selectedUserId()).pipe(
takeUntilDestroyed(this.destroyRef),
catchError(() => of([] as ToDo[]))
).subscribe(
tasks => this.userTasks.set(tasks)
)
);
// Option 2:
// Create a writable signal.
// Use an effect to react to the userId changes
// Get the data using the parameter
// Use tap to set the writable signal
// Use takeUntilDestroyed() to ensure the Observable is destroyed
// when the component is destroyed
// Subscribe to that Observable
userTasks2 = signal([]); // Writable signal
destroyRef2 = inject(DestroyRef); // Current "context" (this component)
tasksEffect2= effect(() =>
this.http.get(this.todoUrl + this.userService.selectedUserId()).pipe(
tap(tasks => this.userTasks2.set(tasks)),
takeUntilDestroyed(this.destroyRef2),
catchError(() => of([] as ToDo[]))
).subscribe()
);
// Option 3:
// Create a writable signal.
// Create an Observable from the selectedUserId signal
// React to emissions, piping the userId through an Observable pipeline
// Use switchMap to get the data
// Use toSignal to automatically subscribe and unsubscribe
userTasks = signal([]); // Writable signal
private userTasks$ = toObservable(this.userService.selectedUserId).pipe(
switchMap(userId => this.http.get(this.todoUrl + userId).pipe(
tap(tasks => this.userTasks.set(tasks))
)),
catchError(() => of([] as ToDo[])) // on any error, just return an empty array
);
// This signal is not used
// It's only here to automatically handle the subscribe and unsubscribe.
readOnlyUserTasks = toSignal(this.userTasks$, { initialValue: [] as ToDo[] });
a "WHY do we do this" would be nice :)
Thank you for your feedback. The "why" is important indeed.
A follow up question: "why" which in this particular video?
Why to use signals? I mentioned about 1:07 that the intro to signals, including the why, is in a separate video aptly entitled: "Angular Signals: What, Why, and How?" I didn't repeat that content in this video.
Or do you mean "why" to use state?
I am using this video as my template for migrating my project from observables to signals.
// To react to events when the is closed | sucess | reject | cancel
private uaSelectedActionSubject = new BehaviorSubject('');
uaSelectedActionMessage$ = this.uaSelectedActionSubject.asObservable();
// Replace the uaAction with uaSelectedActionMessage$
uaAction = signal('');
Nice!