@@RainerHahnekamp Great, RxJS is also very interesting topic so I will surely watch it. Btw. RxJs is broad topic so I'm not expecting that you will touch this subject in mentioned video but for future content you could consider adding to your 'pool of ideas' reactive/declarative vs imperative style of programming in context of RxJs (it's not so obvious for many programmers who are used to write imperative code - me included)
@@youpeekayeyI touched a little bit on it. I think that RxJs forces you to do declarative programming and I have seen very often that people overuse that paradigm. So I have an example where I show how simple it can become if you add a little bit of side effects into it. We will see 😅
Fantastic content, brilliantly explained. I really appreciate the step by step changes and taking the time to explain why each error occurs. Master at work! Thank you for making and sharing this Rainer!
Great video! It'll take a while for me to really understand some concepts, especially since we haven't been using Signals yet, and we've only just upgraded to v17. However, I'm excited about the future of both Signals and RxJS. :)
Rainer, really good videos. Been following you for some time and enjoy your simple way of explaining. If you can, do you have more videos about the signalStore and it extensibility? I use it a lot and I know how powerful it is, but would love to see more examples,
Hi Franco, thanks a lot. If you give me some examples, I could do a video. The problem with the extensions is that they require very quickl an advanced knowledge of TypeScript. So it is important to find the right balance.
@@RainerHahnekamp Hi Rainer, thanks for your response. I agree, my biggest pain has been understanding the typing. Luckily, Manfred article "NGRX Signal Store Deep Dive: Flexible and Type-Safe Custom Extensions" explained it, but it took me quite some time to understand it. After reading that article I realized how powerful the signalStoreFeature is. I personally would like to see some more examples on creating reusable extensions that can be used with and without collectionProps, but also some variations of the SignalStoreFeature. Thanks again for your amazing videos
Yeah, about that article of Manred's. We had a discussion internally about the trade-off between readability and the power it brings. After all, you have some code, which very likely most of your developers cannot maintain but only use. I'd rather create separate stores before I go into the technical challenges with those dynamic property names I'd say it is fine as long as it can be implemented using generic functions. However, I'd be a little bit careful as soon as mapped types are required. Either way, I will keep that thought in mind and if I have enough extensions, I might come up with a video.
Regarding 46:00 I think it's much simpler: the effect() takes an arrow function. If no signals inside that function emitted changed value since last change detection cycle, then the whole arrow function is not executed, but if any one or more have their values changed, then the whole arrow function is executed. Also, I believe it uses reference equality to tell if signal should produce a new value to consumers. That's why immutability of the internal state is so important.
@@RainerHahnekamp I mean the logic to run or not run the effect lambda is probably determined by whether any one or more of the tracked signals associated with it have a new value or not.
@@ml_serenity Yes, but dynamic dependency tracking does exist: github.com/angular/angular/tree/main/packages/core/primitives/signals#dynamic-dependency-tracking
Thanks for sharing - great content! My only point would be, you start going straight into coding with a project you created before the video. Would it be possible to get a GH repo that we can clone to code alongside you? I would like to build the app, too :)
Yes, here is a branch that contains the project as it was at the beginning of the recording: github.com/rainerhahnekamp/signals-unleashed/tree/init. Is that what you were looking for?
Great video Rainer, all concepts well explained. I have also a course about Angular Signals in my channel but it's in Spanish with translations in English!
Thanks, that's exactly what I have to teach my team. Currently I experiment with various patterns to combine signals with async service calls. Chaining them is not yet very readable with toSignal/toObservable calls. It's not very "pipable". But we will see...
Lars, when you have to use RxJs quite intensively, then I would try to make a hard split: Use RxJs in services and Signals in components. Signal-based state management, like the NgRx Signal Store, might also help.
@51:37 In the constructor, when using an effect and setting type to 'city', it knows not to update it because its the same value as it was before. What if instead of type being a string, it was an object? where we set a property of an object? Does it deep compare objects as well? or does it compare only the primitive types for detection?
Hey, nope for the deep compare. The signal does the equal check based on object reference. That's why a you need to do an immutable update of the state, i.e. clone the object. You can add an equals function, as second parameter of the computed function. Then you are in charge. That is something I haven't shown in the video.
Thanks for a great video! I am kind of confused about why the Angular core team (normally very opionated) is not proposing an official stance on how to structure code regarding async calls together with Signals for the best performance and maintainability? Do you have any thoughts about that Rainer? They say use Signals for state and they expose some interop functions for RxJS but has no official documentation for the process of... 1. Reacting to an Input signal (lets say an ID) 2. Fetching data based on the value of the signal 3. Ending up with a new signal that holds the data required to render the component.
Thanks a lot as well. According to my information, the Angular team is aware that Signals alone will not be enough for holding larger state and complexity. Depending on the use case, there are different ways on how to implement them. That's why they decided to have regular discussions with the various authors of state management libraries. They want that the "community" develops patterns first before they (if at all) bring it into the framework. As for the asynchronous operation, I would go with an effect (and untracked) that reacts on a Signal change. But this is already something where a State Management library might be useful. I generally go with the NgRx SignalStore.
Thank you for the bombshell video Rainer! While these Signal APIs vastly simplify how components/directives React to Changes, I feel that we still have not arrived at a good pattern for the Initialization phase of components/directives using Signal APIs. Scheduling Initialization in constructor using the afterNextRender() seems to be the most sensible approach for me, with the added benefit of being SSR-friendly I also tried setting up Initialization using effect() and untracked() but in the end it felt a bit "unsafe" because effect execution is asynchronously dependent on Change Detection Scheduling, which we have very little control over. I am also concerned about when the executed effect is itself an asynchronous fetch, like in your demo (the async search function). ngOnInit, on the other hand does not have access to viewChild() and contentChild(), unless these queries are marked static. Perhaps you can provide more insight regarding the advantages/disadvantages of the above approaches in future videos, when best practices emerge!
Hey, it sounds to me like you are afraid of loosing the control over things? I don't see it that way to be honest. Yes, an effect runs asynchronously but if it triggers a side-effect which is also asynchronous (e.g. HTTP request), it doesn't change anything. I was never in control of an HTTP request either. Would it be possible to elaborate your issue a little bit? Can you think of a use case where the new API might be a problem? --- I would be careful when it comes to afterNextRender and SSR. It is not executed on the serve. So your rendered page might be missing crucial content. --- Cheers!
I would say it's the timing of the availability of various component signals during the initialization that causes me some confusion. Like if I tried to 1. read an input.required() signal, 2. then fetch some data in an effect(), 3. and then use that data to populate a 3rd-party chartJS node in the DOM using viewChild() => I'm not exactly sure where should I schedule this chain of behaviour, because input.required() cannot be read too early in the constructor (input not yet available error would be thrown), while effect() itself must be scheduled in an injection context (constructor or field declaration), when viewChild() result definitely is not yet available in constructor. With decorator based approach, I would say ngOnInit for reading @Input and fetch data, then afterViewInit for populating chartJS DOM node. I'll need to study that part of your video again to familiarize myself with these new timings. Thanks
Effects don't see all value updates because the JavaScript event loop is single threaded and the effects are only executed after the current execution context has finished and the deferred event loop is drained. I'm pretty sure the only way that computed signals and effects automatically register their dependencies is that they record what signals are called during their execution; and more importantly this is only possible because JavaScript is single-threaded. I assume that there is a global register that is used to accumulate a list of called signals during the execution of an effect or computed and that is used to register the dependencies and listen for updates. This only works if only one effect or computed is able to be executed at a time.
You are absolutely right with your description on how computed and effects register themselves. I would describe the execution of an effect a little bit different though. It is when Angular decides that it is now time to start updating the DOM. So effects run asynchronously but if you have scheduled asynchronous task with a timeout, the the effect will run before them.
@@RainerHahnekamp If that is the case (setTimeout executes aftwards), then that means the effect is executed within the same callstack as the update to the dependency signal and does not use the JS event loop. The event loop processes queued tasks (aka messages) sequentially, in the order in which they are added to the queue. It is my understanding that there is no way to prioritize those tasks, other than using the delay argument of the setTimeout and setInterval methods.
@@sheariley1910 Angular itself is the one that triggers the effect when it does the change detection. So it is not like the effect is natively executed by the engine. You could also see it in a different way. The signals update their consumers immediately about the change. So the consumers always know that they are "dirty" but it is up to the framework when to actually tell them "to put their cards on the table". I've tried to explain it in my video with the animation where I used the term "caller". I might also quote from the official documentation, where they say the time when the effect is called is unspecified: github.com/angular/angular/tree/main/packages/core/primitives/signals#side-effects-createwatch
@RainerHahnekamp Angular is written in JavaScript and runs in the JavaScript environment. So I'm not sure what you mean by "the effect is not executed natively by the engine". Angular's signal framework code is either executing the dependent effects as part of the callstack initiated by an update to a dependency signal or it is queuing that execution as a deferred task which is processed by the event loop. Its one or the other. Those are the only 2 possibilities. So if what you are saying is true, then it has to be the former. This is fine. I was just making an observation. Also, this should make it easier to follow the stack trace when debugging and makes the whole thing more deterministic; both great things.
@@sheariley1910 I hope we don't misunderstand each other and talk about two different things. Angular has an own scheduler when the effect execution happens. When it comes down, it will of course be the JavaScript engine that runs it. You can find the scheduler here: github.com/angular/angular/blob/main/packages/core/src/render3/reactivity/effect.ts Little bit complicated but you get the idea.
Great video! I am really looking forward to working with v17+. I am personally a big fan of React, and I am happy to see Angular going towards something that feels more familiar to me. It would be cool if the effects worked like React. You give it a list of which signals can cause it to trigger. The automatic triggering based on signals being referenced is cool, but also very dangerous as you mention. And having to wrap that in untrack just seems less elegant than an array of signals which can cause an update. Sad that they didn't want the explicit list of signals.
Hi there, happy to hear you liked my video. So in the meantime I had the chance to discuss this with some deveopers of the Angular team they're that they really want to keep it as it as know. That means no explicit Signal tracking is planned. Either way, I think using the untracked needs to become a known pattern and then we are all happy for now. Maybe over time, when collect more experience on the usage of Signals, the Angular might introduce that change OR it could also be that the complete Angular API is Signal based and we don't need the effect anymore. I doubt the last point, but let's see wht the future brings 😄
@@RainerHahnekamp One day, maybe it will all be signals, that would be cool 😉 But yeah, the untrack has to be one of the things people have to know about. Thank you for responding 😀
Thanks, every template because this is where Angular, as framework, acts as "consumer" of the Signals. I defined "template" and "effect()" as reactive context. You could also count the computed to it because it gets notfiied by its producer. I decided against it, since it doesn't process until it is accessed via the template or an effect(). Does that answer your question?
Hi thanks, I am using IntelliJ. It does that by default. But I'd say that this also has to be possible in VSCode in some way. What be surprised if there is no extension available.
Your example on toSignal() appears a simple solution, but in my experience, sometimes it is not appropriate to provide an arbitrary initial value, in which case signals don't work. I think this is an anti pattern. To me it seems more logical an architecture to wait for the real value from the database, rather than scattering around arbitrary starter values, which may have unexpected consequences (e.g. in effects that do calculations).
Well, I wouldn't say it is an anti-pattern. Especially not in the way how I used it. If it comes to HTTP Response, as you mentioned it, it is a little bit more complicated. First of all, a Signal forces us to provide a value. The alternative would be to have a union type with undefined. Sticking to an Observable is not really option if we consider that Angular is heading towards Signal Components. Another option is that you add metadata to that Signal which tells you, if you already have the response or if the signal's value is still the initial one. But again, with that approach you'll find yourself very quickly in a situation where you want to use a Signal-based state management library. So it starts to become more complicated although you might have a simple use case.
Hi how do you feel about calling a private method in a computed signal that could hide a lot, i.e. what signal(s) the computed one depends on? I kind of try to read the signals value first and pass them as function parameters for better readability...
Hi, you would have to show me some kind of code so that I can get an understanding of your use case. In general, I would avoid calling methods inside a computed. You don't know what the private method is doing exactly. If the method calls another Signal you have an implicit/hidden tracking of that one. If your method starts an asynchronous task, then you are problay using it wrong and have to find further workarounds, which doesn't really improve the code. On the other side, if the computed is derived by a very complicated algorithm which you want to re-use outside of the computed as well, then yes. That makes sense. But please be free to share a code snippet. You might have a use case I haven't thought about so far.
Excellent video. Many thanks. Been using react for sevral years, with mobx for state management. Signals seem very close to how mobx works. What is your thought on using signals for application state as well?
Thanks, so representing state which changes over time is the primiary purpose of Signals. Or did you mean as an alternative to a full-blown state management library?
@@bellosthomas Ah, I see. So I don't think this is a good idea because you need a little bit more functionality. For example dealing with parts of the Signal, and improving updating them. Usually there is always some logic around Signals which you also want to have next to the Signal itself. In this case, a state management library which is built on top of Siganls does make sense. I would go with the Signal Store (I've actually made two topics about it, I'd recommend the second one as a starter). You might be interested in watching this Short as well, where Alex Rickabaugh, tech lead of the Angular framework, discusses the same question: ruclips.net/user/shortsvgzC9xHedyw
@@RainerHahnekamp if am not mistaken ngrx is the redux counterpart of react. I am not a fan of redux so I try to avoid it. Will check the link. Many thanks
@@bellosthomasSo NgRx has the global store, the component store and now the signal Store. The global store is the one with the redux pattern. Signal and Component Store are without it.
Hey, I'm not using VSCode but IntelliJ. it has that built-in. It is called inlay hints and should also work in VSCode: code.visualstudio.com/docs/typescript/typescript-editing#_inlay-hints
I am having a hard time starting the application. I switched to init branch, and i followed the instructions in installation.md file, but nothing worked
Nice work! What do you think of reactive forms working together with signals. I always have the feeling it doesn't go well together (like 2 different worlds). Especially if i also use signal stores. In the beginning of Angular 2 I had the feeling that template driven forms were cumbersome. I don't know if now there is a trend again towards template driven forms?
Hello, and thanks. The "New API" in my video is just the beginning. The complete API of the framework has to transition to Signals as well. That will include - as you mentioned it - the Forms as well. For some time, the Angular team said that they wanted to come out with a new Signal-based form that would succeed the template-driven and Reactive Forms. At the ng-conf, they announced that they might want to introduce Signals already into the ReactiveForms and provide the new Form in a separate step later.
I heard that effect() is only for logging/debugging purposes. Am I right? And could you please tell me what can I use inside it and what should I avoid, technically ?
No, you use the effect() whenever computed() can't do the job. Depending on your application, it could happen that effect() shows up very rarely, but the opposite could also be true. Logging is one use case, but it also involves accessing the DOM when a signal changes or setting values in a reactive formgroup (also when a signal changes). In Angular 19, we received linkedSignal and resource. This are functions, made for a specific use cases where you had to use effect in the past.
@@RainerHahnekamp so, for example if the signal is used for a stream of data from a sensor, and I want to manipulate/calculate the data I get and right after that use it in threeJS to update my 3D model, lets say move it, should I use computed or effect for this purpose? please consider that the data is being received non-stop each 1ms or each frame of DOM being rendered
@@nobodyeverybody8437 Oh, that's not so easy to answer. The time period for a frame is already at 16.6ms. If technically even possible, user would only get to see every 16/17th value. If you put the value into a Signal and use an effect, created in a component, that effect will run on every change detection (to be precise as part of the change detection). So that can work. The more important question is how you want to do the calculation and if you need to manage the stream in some way? If the answer is yes, then RxJs with its powerful pipe operators like debounceTime, buffer might be a better choice. I'd say if it is just about simple calculations, then Signals should work, if not it becomes trickier.
If we update signal in an effect not aware of it could go into infinite loop. Will angular gives any warning? I think while implementing complex functionality developer may get into updating multiple effects that can lead to infinite loop, it is better angular should warn.
So first of all, you have to disable the built-in protected via untracked or allowSignalWrites. Once it is disable, you are responsible for whatever you do: n = signal(1); #loop = effect( () => { console.log('loop'); this.n.set(this.n() + 1); }, { allowSignalWrites: true }, ); That is an infinite loop. Very easy to achieve 😇
Hello guys, Do you know why the api for optional input signal (with initialValue?) and required input signal (without the possibility to initialize in the component are different ) ? I understand that the required input should be fill by the caller, but for some use case, these inputs are not always fill. Example: Create component with TestBed, required input are not mandatory to instantiate the component. Same for import dynamic import(‘’).then Or the usage of ViewContainerRef. Why the initialValue is not proposed as alternative for required input ? Thanks in advance 🫡
To me, it wouldn't make any sense to provide an initial value for the required.I already defined with required that there has to be a value. A required without value would therefore be a state that can't exist and I'd expect an error to be thrown. The same is true for tests. If you don't pass a value to a required input property, it should throw as well. To me a required with initial value is the same as an input with a default value. Where would you see the difference?
@@RainerHahnekamp When I was watching this, my wife came in, and I said this is a guy I was chatting with just last month in Salt Lake City :) This approach has more characters than the assertion or the generics, but I like it better. I really try to avoid `as` in production code.
Hello, because initially the loading component has isLoading set to false and I immediately switch it to true. That's what Angular detects and why it shows the error. That type of error can occur in different scenarios. Usually it happens in a non-Signal application but it could also happen with Signals, especially if you are making heavy use of the effect function. I am not sure, if that answers your question. Was it more generic about the error itself or more application-specific?
@RainerHahnekamp Hallo. Ich mag deine Videos und habe schon viel daraus gelernt. Habe meiner derzeitige Angular-Anwendung auf Signals umgestellt und es macht einfach Spaß. Gibt es eine Möglichkeit dir spezifische Fragen zu stellen außer hier über die Kommentare? Eine Frage die ich schon länger habe: Was ist der Ansatz momentan einen "heartbeat" in Angular zu machen. Also die Anwendung startet, der Heartbeat service startet und versucht sich mit dem backend zu connecten. Jede Sekunde wird geschaut ob das backend noch erreichbar ist, ansonsten wird im store auf "not connected" umgestellt. Was wäre der modere Weg so einen perodischen "Ticker" zu machen? Danke, lg
Hi @Mark, I'll answer first in English and then in German. So your question was for a "heartbeat" pattern: The application should regularily check, if the backend is reachable and should expose a status property like 'connected' | 'not connected'. I'd to that via a simple service which is provided in root. That guarantees you that you have a singelton and I would inject it in the app.component or in a special component that visually shows the status to the end user. I've updated the repository. It comes now with a HeartbeatService: github.com/rainerhahnekamp/signals-unleashed/blob/main/src/app/heartbeat.service.ts --- from now on German --- Also ich denke einmal, dass du das englische eh soweit verstanden hast. Grundsätzlich kannst mir allgemeine Fragen auch hier ins Video reinposten oder du schreibst mich direkt auf meine Mail [vorname].[nachname]@gmail.com an. LinkedIn geht natürlich auch immer. Beim HeartbeatService hab ich dir noch ein Event dazugetan, was zusätzlich reagiert, wenn vom Browser die Meldung "offline" durchkommt. Denke, dass das auch Sinn macht. Wenns vom Beispiel her noch Fragen gibt, einfach wieder melden, gell!
@@RainerHahnekamp Thank you. I think i wrote in german because i read you are from austria - like me. Thanks for the HeartbeatService. I have a similar approach and its good to see how an expert would do it ;)
@@HeskmarkAh, I see. My version is not stable though. If the browser goes offline, the Signal would get this information immediately, but because that event is not picked up by zone.js the UI updates in the next interval cycle. The only way how to fix this, is to call cdr.detectChanges(). Hopefully I can come up with a better one. Best wishes from Wien!
@@RainerHahnekamp Yesterday, I pulled the init branch and started the tutorial, and everything was OK. Today, when I launched the application with ng serve, the server started successfully, but when I go to localhost:4200, I only see the header and the page content is blank. After 5 seconds, I get a timeout. It's as if the frontend is trying to connect to a remote server without getting a response. I can send you a screenshot if you want.
@@RainerHahnekamp Yesterday, I pulled the init branch and started the tutorial, and everything was OK. Today, when I launched the application with ng serve, the server started successfully, but when I go to localhost:4200, I only see the header and the page content is blank. After 5 seconds, I get a timeout. It's as if the frontend is trying to connect to a remote server without getting a response. I can send you a screenshot if you want.
@@RainerHahnekamp Yesterday, I pulled the init branch and started the tutorial, and everything was OK. Today, when I launched the application with ng serve, the server started successfully, but when I go to localhost:4200, I only see the header and the page content is blank. After 5 seconds, I get a timeout. It's as if the frontend is trying to connect to a remote server without getting a response. I can send you a screenshot if you want.
Saleem, that's IntelliJ what I'm using. If you mean the inlay Hints, they are available in VSCode as well: code.visualstudio.com/docs/typescript/typescript-editing#_inlay-hints
Hi, thank you very much. About the dark mode, is there a specific reason or just a matter of taste? I have been told that I should use light mode for that kind of presentations.
@@RainerHahnekamp Way easier/healthier on the eyes, especially if you, like me as a java-dev, spend 8 hours a day already behind a screen. We get recommanded to use dark mode with everything as much as possible (IntelliJ, Postman, Docker, Teams, ...). Almost every piece of software has a dark mode these days, and for a good reason. 🙂 In the end it is personal preference, but i can assure you, once you get used to dark mode, it is so much nicer to work, and your eyes will be thankful in the long run. Just think about your gps in your car, when it's nighttime, it also automatically switches to dark mode, seems strange, but that is because the contract is very tiring and unhealthy for your vision + alot of people watch youtube after their work or in the evening so when it is dark/getting darker. Hope this was helpful! 🙂 ps: please continue making great video's!
Come on really 😅? To me it is the opposite. Every time I work with dark mode, I am almost blind. I mean, if dark mode is better for the eyes or you and the other views have an easier time to read it, it is definitely an option. What I've found though, is the opposite: www.allaboutvision.com/digital-eye-strain/is-dark-mode-better-for-eyes/ I also remember that during the beginning of Covid, I got the recommendation to use light mode whenever I do a recording. If you more information, please let me know.
Really thoroughly explains Signals with clear, relevant examples. Nicely done, thank you!
Thank you
You rock! fabulous work man, this is the most full detailed explanation I ever watched, thanks for the great content!
Hey, thanks a lot!
Thanks!
Wow, thank you!
Fantastic, Rainer! A comprehensive overview of the signals API and beyond...
Thanks Israel, happy to hear.
As usual, excellent trainer. THANKS
Thanks again Roland!
Sweet mama, fantastic stuff. Most in-depth guide in this topic that i found on yt. Thanks for this and keep up with great work! And subscribed ;)
Thanks Doman, will do. The next "big one" will be about RxJs and a little bit longer.
@@RainerHahnekamp Great, RxJS is also very interesting topic so I will surely watch it.
Btw. RxJs is broad topic so I'm not expecting that you will touch this subject in mentioned video but for future content you could consider adding to your 'pool of ideas' reactive/declarative vs imperative style of programming in context of RxJs (it's not so obvious for many programmers who are used to write imperative code - me included)
@@youpeekayeyI touched a little bit on it. I think that RxJs forces you to do declarative programming and I have seen very often that people overuse that paradigm. So I have an example where I show how simple it can become if you add a little bit of side effects into it. We will see 😅
Accidentally landed in this video. Now he's my favourite instructor. Amazing Rainer😍
@@nithin_bd accidentally??? 😅 where did you initially want to go? Well, welcome 🤗
@@RainerHahnekamp I was casually browsing RUclips 😂
@@nithin_bd 🙋♂👍
Thanks for this. Also, your audio is much better in this video than some of your older ones.
Thanks as well. I have an idea of a particular video where the audio was not so good 😅
Fantastic content, brilliantly explained. I really appreciate the step by step changes and taking the time to explain why each error occurs. Master at work! Thank you for making and sharing this Rainer!
Thanks a lot Christian. Happy to hear. Yeah, I guess it is extremly important to have an understanding of the root causes of potential errors.
This video really great. Thank you for that!
You are very welcome. Happy you liked it.
I am so greatful! I will share this with my team, so we can easily bring everybody to the same understanding of Signals pretty quickly! Thank you!
Great, thanks, happy to hear and see you soon again in real life :)
Absolutely awesome Rainer. A complete overview of signals API and more ...
Thanks Dhaval, was a long recording and post-production session as well :)
Thank you for this course! Finally i could understand how to use Signals!
Thanks, that's nice to hear!
Great Job. Thank you for all the videos and articles you share with the community, it helps a lot.
Thanks, I hope I can publish new videos very soon.
Great video!
It'll take a while for me to really understand some concepts, especially since we haven't been using Signals yet, and we've only just upgraded to v17. However, I'm excited about the future of both Signals and RxJS. :)
@@DS-bz4mz Thanks, well if you are on 17 now, it is time to make use of them 👍
Rainer, really good videos. Been following you for some time and enjoy your simple way of explaining.
If you can, do you have more videos about the signalStore and it extensibility? I use it a lot and I know how powerful it is, but would love to see more examples,
Hi Franco, thanks a lot. If you give me some examples, I could do a video. The problem with the extensions is that they require very quickl an advanced knowledge of TypeScript. So it is important to find the right balance.
@@RainerHahnekamp Hi Rainer, thanks for your response. I agree, my biggest pain has been understanding the typing.
Luckily, Manfred article "NGRX Signal Store Deep Dive: Flexible and Type-Safe Custom Extensions" explained it, but it took me quite some time to understand it.
After reading that article I realized how powerful the signalStoreFeature is.
I personally would like to see some more examples on creating reusable extensions that can be used with and without collectionProps, but also some variations of the SignalStoreFeature.
Thanks again for your amazing videos
Yeah, about that article of Manred's. We had a discussion internally about the trade-off between readability and the power it brings. After all, you have some code, which very likely most of your developers cannot maintain but only use. I'd rather create separate stores before I go into the technical challenges with those dynamic property names
I'd say it is fine as long as it can be implemented using generic functions. However, I'd be a little bit careful as soon as mapped types are required.
Either way, I will keep that thought in mind and if I have enough extensions, I might come up with a video.
What I found here just Gold, You can't ask better explanation this, thanks for great work you've done here.
Thanks for the compliment!
Excellent explanation. Subscribed
Thanks!
I would like to congratulate you for the excellent work you did in this video, great explanations
Thank you very much. Very nice of you to say that!
Regarding 46:00 I think it's much simpler: the effect() takes an arrow function. If no signals inside that function emitted changed value since last change detection cycle, then the whole arrow function is not executed, but if any one or more have their values changed, then the whole arrow function is executed.
Also, I believe it uses reference equality to tell if signal should produce a new value to consumers. That's why immutability of the internal state is so important.
Hi, what do you mean exactly? The dynamic tracking is an advanced feature and I guess not used in the majority of use cases.
@@RainerHahnekamp I mean the logic to run or not run the effect lambda is probably determined by whether any one or more of the tracked signals associated with it have a new value or not.
@@ml_serenity Yes, but dynamic dependency tracking does exist: github.com/angular/angular/tree/main/packages/core/primitives/signals#dynamic-dependency-tracking
Thank you for your great efforts and for sharing your knowledge, you're simply amazing
Thanks a lot for the compliment.
Thanks for sharing - great content! My only point would be, you start going straight into coding with a project you created before the video. Would it be possible to get a GH repo that we can clone to code alongside you? I would like to build the app, too :)
Yes, here is a branch that contains the project as it was at the beginning of the recording: github.com/rainerhahnekamp/signals-unleashed/tree/init.
Is that what you were looking for?
Great video Rainer, all concepts well explained. I have also a course about Angular Signals in my channel but it's in Spanish with translations in English!
Thanks Amos, I briefly took a look at them. There are some sections in your videos which are an extrem deep-dive. Congrats.
That is amazing video. Thank you so much for sharing with us. Brilliant work!
Great, happy to hear. Thanks and you are very welcome!
Thanks, that's exactly what I have to teach my team. Currently I experiment with various patterns to combine signals with async service calls. Chaining them is not yet very readable with toSignal/toObservable calls. It's not very "pipable". But we will see...
Lars, when you have to use RxJs quite intensively, then I would try to make a hard split: Use RxJs in services and Signals in components. Signal-based state management, like the NgRx Signal Store, might also help.
@51:37 In the constructor, when using an effect and setting type to 'city', it knows not to update it because its the same value as it was before. What if instead of type being a string, it was an object? where we set a property of an object? Does it deep compare objects as well? or does it compare only the primitive types for detection?
Hey, nope for the deep compare. The signal does the equal check based on object reference. That's why a you need to do an immutable update of the state, i.e. clone the object. You can add an equals function, as second parameter of the computed function. Then you are in charge. That is something I haven't shown in the video.
seems simple when you explain thanks 😀
Thanks as well :)
Thank you very much for sharing your knowledge.
Great content.
Thanks as well!
Great video, very clear explanation, thank you very well!
Thanks as well. And if someting is unclear and you have any questions, let me know!
It is great information. I can’t wait for the next video. 🎉🎉
Thanks Ahmad!
Thanks for a great video! I am kind of confused about why the Angular core team (normally very opionated) is not proposing an official stance on how to structure code regarding async calls together with Signals for the best performance and maintainability? Do you have any thoughts about that Rainer?
They say use Signals for state and they expose some interop functions for RxJS but has no official documentation for the process of... 1. Reacting to an Input signal (lets say an ID) 2. Fetching data based on the value of the signal 3. Ending up with a new signal that holds the data required to render the component.
Thanks a lot as well.
According to my information, the Angular team is aware that Signals alone will not be enough for holding larger state and complexity. Depending on the use case, there are different ways on how to implement them.
That's why they decided to have regular discussions with the various authors of state management libraries. They want that the "community" develops patterns first before they (if at all) bring it into the framework.
As for the asynchronous operation, I would go with an effect (and untracked) that reacts on a Signal change. But this is already something where a State Management library might be useful. I generally go with the NgRx SignalStore.
Just amazing explanation, thank you very much!!!
Great to hear. Thanks a lot as well!
Thank you very much. It’s helped me a lot.😊
Great, that’s what I was hoping for 👍 good to hear
Thank you for the bombshell video Rainer!
While these Signal APIs vastly simplify how components/directives React to Changes, I feel that we still have not arrived at a good pattern for the Initialization phase of components/directives using Signal APIs.
Scheduling Initialization in constructor using the afterNextRender() seems to be the most sensible approach for me, with the added benefit of being SSR-friendly
I also tried setting up Initialization using effect() and untracked() but in the end it felt a bit "unsafe" because effect execution is asynchronously dependent on Change Detection Scheduling, which we have very little control over. I am also concerned about when the executed effect is itself an asynchronous fetch, like in your demo (the async search function).
ngOnInit, on the other hand does not have access to viewChild() and contentChild(), unless these queries are marked static.
Perhaps you can provide more insight regarding the advantages/disadvantages of the above approaches in future videos, when best practices emerge!
Hey,
it sounds to me like you are afraid of loosing the control over things? I don't see it that way to be honest. Yes, an effect runs asynchronously but if it triggers a side-effect which is also asynchronous (e.g. HTTP request), it doesn't change anything. I was never in control of an HTTP request either.
Would it be possible to elaborate your issue a little bit? Can you think of a use case where the new API might be a problem?
---
I would be careful when it comes to afterNextRender and SSR. It is not executed on the serve. So your rendered page might be missing crucial content.
---
Cheers!
I would say it's the timing of the availability of various component signals during the initialization that causes me some confusion.
Like if I tried to
1. read an input.required() signal,
2. then fetch some data in an effect(),
3. and then use that data to populate a 3rd-party chartJS node in the DOM using viewChild()
=> I'm not exactly sure where should I schedule this chain of behaviour, because input.required() cannot be read too early in the constructor (input not yet available error would be thrown), while effect() itself must be scheduled in an injection context (constructor or field declaration), when viewChild() result definitely is not yet available in constructor.
With decorator based approach, I would say ngOnInit for reading @Input and fetch data, then afterViewInit for populating chartJS DOM node.
I'll need to study that part of your video again to familiarize myself with these new timings.
Thanks
Great video! Thank you for sharing your knowledge ;)
Thanks as well, Michael!
Very nice video, I learned a lot from it that was very fuzzy before.
Thanks for the compliment Dave
Effects don't see all value updates because the JavaScript event loop is single threaded and the effects are only executed after the current execution context has finished and the deferred event loop is drained. I'm pretty sure the only way that computed signals and effects automatically register their dependencies is that they record what signals are called during their execution; and more importantly this is only possible because JavaScript is single-threaded. I assume that there is a global register that is used to accumulate a list of called signals during the execution of an effect or computed and that is used to register the dependencies and listen for updates. This only works if only one effect or computed is able to be executed at a time.
You are absolutely right with your description on how computed and effects register themselves. I would describe the execution of an effect a little bit different though. It is when Angular decides that it is now time to start updating the DOM. So effects run asynchronously but if you have scheduled asynchronous task with a timeout, the the effect will run before them.
@@RainerHahnekamp If that is the case (setTimeout executes aftwards), then that means the effect is executed within the same callstack as the update to the dependency signal and does not use the JS event loop. The event loop processes queued tasks (aka messages) sequentially, in the order in which they are added to the queue. It is my understanding that there is no way to prioritize those tasks, other than using the delay argument of the setTimeout and setInterval methods.
@@sheariley1910 Angular itself is the one that triggers the effect when it does the change detection. So it is not like the effect is natively executed by the engine.
You could also see it in a different way. The signals update their consumers immediately about the change. So the consumers always know that they are "dirty" but it is up to the framework when to actually tell them "to put their cards on the table".
I've tried to explain it in my video with the animation where I used the term "caller".
I might also quote from the official documentation, where they say the time when the effect is called is unspecified: github.com/angular/angular/tree/main/packages/core/primitives/signals#side-effects-createwatch
@RainerHahnekamp Angular is written in JavaScript and runs in the JavaScript environment. So I'm not sure what you mean by "the effect is not executed natively by the engine". Angular's signal framework code is either executing the dependent effects as part of the callstack initiated by an update to a dependency signal or it is queuing that execution as a deferred task which is processed by the event loop. Its one or the other. Those are the only 2 possibilities.
So if what you are saying is true, then it has to be the former. This is fine. I was just making an observation. Also, this should make it easier to follow the stack trace when debugging and makes the whole thing more deterministic; both great things.
@@sheariley1910 I hope we don't misunderstand each other and talk about two different things. Angular has an own scheduler when the effect execution happens. When it comes down, it will of course be the JavaScript engine that runs it. You can find the scheduler here: github.com/angular/angular/blob/main/packages/core/src/render3/reactivity/effect.ts Little bit complicated but you get the idea.
Great video thank you!
You are welcome. 😀
Great video! I am really looking forward to working with v17+.
I am personally a big fan of React, and I am happy to see Angular going towards something that feels more familiar to me.
It would be cool if the effects worked like React. You give it a list of which signals can cause it to trigger. The automatic triggering based on signals being referenced is cool, but also very dangerous as you mention. And having to wrap that in untrack just seems less elegant than an array of signals which can cause an update. Sad that they didn't want the explicit list of signals.
Hi there, happy to hear you liked my video.
So in the meantime I had the chance to discuss this with some deveopers of the Angular team they're that they really want to keep it as it as know. That means no explicit Signal tracking is planned.
Either way, I think using the untracked needs to become a known pattern and then we are all happy for now. Maybe over time, when collect more experience on the usage of Signals, the Angular might introduce that change OR it could also be that the complete Angular API is Signal based and we don't need the effect anymore.
I doubt the last point, but let's see wht the future brings 😄
@@RainerHahnekamp One day, maybe it will all be signals, that would be cool 😉 But yeah, the untrack has to be one of the things people have to know about. Thank you for responding 😀
@@ManifibellSure thing, you are very welcome 👍
Really great video. Thanks for posting a detailed video. Any guide on What is the reactive context? Every view is considered as reactive context ?
Thanks, every template because this is where Angular, as framework, acts as "consumer" of the Signals. I defined "template" and "effect()" as reactive context. You could also count the computed to it because it gets notfiied by its producer. I decided against it, since it doesn't process until it is accessed via the template or an effect().
Does that answer your question?
Yes. Thanks for the quick response
Good explanation. Can i ask what ide your using with the tooling inserting the greyed types etc.
Hi thanks, I am using IntelliJ. It does that by default. But I'd say that this also has to be possible in VSCode in some way. What be surprised if there is no extension available.
Super!)) I`m understanding how it works. Thank you!)
Great, you're welcome
@@RainerHahnekamp can you explain how to make something like that work?
loadVideos$: Observable = createEffect(() => {
return this.actions$.pipe(
ofType(VideoActions.loadVideos),
switchMap(() =>
computed(() => this.searchService.searchQuery$).pipe( this
switchMap((query: string) =>
computed(() => this.navigationService.currentTokenPage$).pipe( and this
switchMap((pageToken: string) =>
this.requestService.search(query, pageToken).pipe(
switchMap((items: Item[]) =>
this.filterService.filter$.pipe(
map(() => this.filterService.sortDataByFilterCriteria(items))
)
),
map((videos: Item[]) => VideoActions.loadVideosSuccess({ videos })),
catchError((error) => of(VideoActions.loadVideosFailure({ error: error.message })))
)
)
)
)
)
)
})
Your example on toSignal() appears a simple solution, but in my experience, sometimes it is not appropriate to provide an arbitrary initial value, in which case signals don't work. I think this is an anti pattern. To me it seems more logical an architecture to wait for the real value from the database, rather than scattering around arbitrary starter values, which may have unexpected consequences (e.g. in effects that do calculations).
Well, I wouldn't say it is an anti-pattern. Especially not in the way how I used it.
If it comes to HTTP Response, as you mentioned it, it is a little bit more complicated. First of all, a Signal forces us to provide a value. The alternative would be to have a union type with undefined. Sticking to an Observable is not really option if we consider that Angular is heading towards Signal Components. Another option is that you add metadata to that Signal which tells you, if you already have the response or if the signal's value is still the initial one. But again, with that approach you'll find yourself very quickly in a situation where you want to use a Signal-based state management library. So it starts to become more complicated although you might have a simple use case.
thanks effect is exactly what I needed.
Glad I could help!
Awesome! Big thanks!
Thanks Ben
Hi how do you feel about calling a private method in a computed signal that could hide a lot, i.e. what signal(s) the computed one depends on?
I kind of try to read the signals value first and pass them as function parameters for better readability...
Hi, you would have to show me some kind of code so that I can get an understanding of your use case. In general, I would avoid calling methods inside a computed.
You don't know what the private method is doing exactly. If the method calls another Signal you have an implicit/hidden tracking of that one. If your method starts an asynchronous task, then you are problay using it wrong and have to find further workarounds, which doesn't really improve the code.
On the other side, if the computed is derived by a very complicated algorithm which you want to re-use outside of the computed as well, then yes. That makes sense.
But please be free to share a code snippet. You might have a use case I haven't thought about so far.
Absolutely amazing!
Thank you very much!
Excellent video. Many thanks. Been using react for sevral years, with mobx for state management. Signals seem very close to how mobx works. What is your thought on using signals for application state as well?
Thanks, so representing state which changes over time is the primiary purpose of Signals. Or did you mean as an alternative to a full-blown state management library?
@@RainerHahnekamp as a full blown state management system
@@bellosthomas Ah, I see. So I don't think this is a good idea because you need a little bit more functionality. For example dealing with parts of the Signal, and improving updating them. Usually there is always some logic around Signals which you also want to have next to the Signal itself. In this case, a state management library which is built on top of Siganls does make sense. I would go with the Signal Store (I've actually made two topics about it, I'd recommend the second one as a starter).
You might be interested in watching this Short as well, where Alex Rickabaugh, tech lead of the Angular framework, discusses the same question: ruclips.net/user/shortsvgzC9xHedyw
@@RainerHahnekamp if am not mistaken ngrx is the redux counterpart of react. I am not a fan of redux so I try to avoid it. Will check the link. Many thanks
@@bellosthomasSo NgRx has the global store, the component store and now the signal Store. The global store is the one with the redux pattern. Signal and Component Store are without it.
very good stuff, thanks for your precious time.
just wondering the vs extension showing those properties definitions
Hey, I'm not using VSCode but IntelliJ. it has that built-in. It is called inlay hints and should also work in VSCode: code.visualstudio.com/docs/typescript/typescript-editing#_inlay-hints
@@RainerHahnekamp thank you very much sir. you've just make my day
thanks, that was a wonderfull overview
You're welcome, happy to hear!
Thanks a lot! Great video!
Random question! What keyboard do you use? It is very satisfying to hear you typing 😊
Hey, that's Mx Keys from Logitech. I usually go with those keyboards, which produce not loud noises and where I don't have to press too hard :)
I am having a hard time starting the application. I switched to init branch, and i followed the instructions in installation.md file, but nothing worked
Yeah, do you have an error message for me?
Nice work! What do you think of reactive forms working together with signals. I always have the feeling it doesn't go well together (like 2 different worlds). Especially if i also use signal stores. In the beginning of Angular 2 I had the feeling that template driven forms were cumbersome. I don't know if now there is a trend again towards template driven forms?
Hello, and thanks.
The "New API" in my video is just the beginning. The complete API of the framework has to transition to Signals as well. That will include - as you mentioned it - the Forms as well. For some time, the Angular team said that they wanted to come out with a new Signal-based form that would succeed the template-driven and Reactive Forms.
At the ng-conf, they announced that they might want to introduce Signals already into the ReactiveForms and provide the new Form in a separate step later.
I heard that effect() is only for logging/debugging purposes. Am I right? And could you please tell me what can I use inside it and what should I avoid, technically ?
No, you use the effect() whenever computed() can't do the job. Depending on your application, it could happen that effect() shows up very rarely, but the opposite could also be true.
Logging is one use case, but it also involves accessing the DOM when a signal changes or setting values in a reactive formgroup (also when a signal changes).
In Angular 19, we received linkedSignal and resource. This are functions, made for a specific use cases where you had to use effect in the past.
@@RainerHahnekamp so, for example if the signal is used for a stream of data from a sensor, and I want to manipulate/calculate the data I get and right after that use it in threeJS to update my 3D model, lets say move it, should I use computed or effect for this purpose? please consider that the data is being received non-stop each 1ms or each frame of DOM being rendered
@@nobodyeverybody8437 Oh, that's not so easy to answer. The time period for a frame is already at 16.6ms. If technically even possible, user would only get to see every 16/17th value.
If you put the value into a Signal and use an effect, created in a component, that effect will run on every change detection (to be precise as part of the change detection). So that can work.
The more important question is how you want to do the calculation and if you need to manage the stream in some way? If the answer is yes, then RxJs with its powerful pipe operators like debounceTime, buffer might be a better choice.
I'd say if it is just about simple calculations, then Signals should work, if not it becomes trickier.
If we update signal in an effect not aware of it could go into infinite loop. Will angular gives any warning? I think while implementing complex functionality developer may get into updating multiple effects that can lead to infinite loop, it is better angular should warn.
So first of all, you have to disable the built-in protected via untracked or allowSignalWrites. Once it is disable, you are responsible for whatever you do:
n = signal(1);
#loop = effect(
() => {
console.log('loop');
this.n.set(this.n() + 1);
},
{ allowSignalWrites: true },
);
That is an infinite loop. Very easy to achieve 😇
Hello guys, Do you know why the api for optional input signal (with initialValue?) and required input signal (without the possibility to initialize in the component are different ) ? I understand that the required input should be fill by the caller, but for some use case, these inputs are not always fill. Example: Create component with TestBed, required input are not mandatory to instantiate the component. Same for import dynamic import(‘’).then Or the usage of ViewContainerRef.
Why the initialValue is not proposed as alternative for required input ?
Thanks in advance 🫡
To me, it wouldn't make any sense to provide an initial value for the required.I already defined with required that there has to be a value. A required without value would therefore be a state that can't exist and I'd expect an error to be thrown.
The same is true for tests. If you don't pass a value to a required input property, it should throw as well.
To me a required with initial value is the same as an input with a default value. Where would you see the difference?
Can you share your IDE setup & extensions
Hi, I am using IntelliJ with the default settings.
@@RainerHahnekamp
Thank you, really enjoyed the video 🙏🙏
At 9:40, there's another approach that doesn't need an assertion: `signal(new Array())`
Hey Lance 👋, nice to meet you on RUclips again. Thanks for that approach, haven't thought about instantiating an Array like this.
@@RainerHahnekamp When I was watching this, my wife came in, and I said this is a guy I was chatting with just last month in Salt Lake City :)
This approach has more characters than the assertion or the generics, but I like it better. I really try to avoid `as` in production code.
@@LMFinney Nice, greetings to your wife :). I've also told mine about your adventures you shared with us.
whats the editor u are using for coding, how the type of variable are shown
That's IntelliJ. I've moved away from VSCode a long time ago.
HI , ExpressionChangedAfterItHasBeenCheckedError occurring due to the loading service but why it is coming from there ?
Hello, because initially the loading component has isLoading set to false and I immediately switch it to true. That's what Angular detects and why it shows the error. That type of error can occur in different scenarios. Usually it happens in a non-Signal application but it could also happen with Signals, especially if you are making heavy use of the effect function.
I am not sure, if that answers your question. Was it more generic about the error itself or more application-specific?
does anybody know which extension is using to show the variable types while typing? Thanks in advance!
That's support by default in IntelliJ. What IDE are you using?
@@RainerHahnekamp visual Code.
Thanks for replying!
@@carlosiglesias8354you might want to look up that one for VSCode: code.visualstudio.com/docs/typescript/typescript-editing
Thanks so much 🎉🎉🎉
@RainerHahnekamp
Hallo. Ich mag deine Videos und habe schon viel daraus gelernt. Habe meiner derzeitige Angular-Anwendung auf Signals umgestellt und es macht einfach Spaß.
Gibt es eine Möglichkeit dir spezifische Fragen zu stellen außer hier über die Kommentare?
Eine Frage die ich schon länger habe:
Was ist der Ansatz momentan einen "heartbeat" in Angular zu machen. Also die Anwendung startet, der Heartbeat service startet und versucht sich mit dem backend zu connecten.
Jede Sekunde wird geschaut ob das backend noch erreichbar ist, ansonsten wird im store auf "not connected" umgestellt. Was wäre der modere Weg so einen perodischen "Ticker" zu machen?
Danke, lg
Hi @Mark, I'll answer first in English and then in German. So your question was for a "heartbeat" pattern: The application should regularily check, if the backend is reachable and should expose a status property like 'connected' | 'not connected'.
I'd to that via a simple service which is provided in root. That guarantees you that you have a singelton and I would inject it in the app.component or in a special component that visually shows the status to the end user.
I've updated the repository. It comes now with a HeartbeatService: github.com/rainerhahnekamp/signals-unleashed/blob/main/src/app/heartbeat.service.ts
--- from now on German ---
Also ich denke einmal, dass du das englische eh soweit verstanden hast. Grundsätzlich kannst mir allgemeine Fragen auch hier ins Video reinposten oder du schreibst mich direkt auf meine Mail [vorname].[nachname]@gmail.com an. LinkedIn geht natürlich auch immer.
Beim HeartbeatService hab ich dir noch ein Event dazugetan, was zusätzlich reagiert, wenn vom Browser die Meldung "offline" durchkommt. Denke, dass das auch Sinn macht.
Wenns vom Beispiel her noch Fragen gibt, einfach wieder melden, gell!
@@RainerHahnekamp Thank you. I think i wrote in german because i read you are from austria - like me. Thanks for the HeartbeatService. I have a similar approach and its good to see how an expert would do it ;)
@@HeskmarkAh, I see. My version is not stable though. If the browser goes offline, the Signal would get this information immediately, but because that event is not picked up by zone.js the UI updates in the next interval cycle. The only way how to fix this, is to call cdr.detectChanges(). Hopefully I can come up with a better one. Best wishes from Wien!
Is it necessary/mandatory for us to learn German first in order to use Signals?
@@nobodyeverybody8437 Austrian 🇦🇹 would also do it.
@@RainerHahnekamp 🙂
Would be nice to provide links that are in the slides in the description so it would be possible to follow those.
Good point, I've added them. For your convenience: speakerdeck.com/rainerhahnekamp/signals-unleashed-the-full-guide
Amazing!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Thank you Dany! All the best!
Best Angular tRainer ;)
THANK YOU!
hello i have start your tuto yesterday, but when i run your git repo, i have;---/**--- We are sorry. An error happened.
Hi Ibrahim, can you help me here a little bit? Which commands returns that error?
@@RainerHahnekamp Yesterday, I pulled the init branch and started the tutorial, and everything was OK. Today, when I launched the application with ng serve, the server started successfully, but when I go to localhost:4200, I only see the header and the page content is blank. After 5 seconds, I get a timeout. It's as if the frontend is trying to connect to a remote server without getting a response. I can send you a screenshot if you want.
@@RainerHahnekamp Yesterday, I pulled the init branch and started the tutorial, and everything was OK. Today, when I launched the application with ng serve, the server started successfully, but when I go to localhost:4200, I only see the header and the page content is blank. After 5 seconds, I get a timeout. It's as if the frontend is trying to connect to a remote server without getting a response. I can send you a screenshot if you want.
@@RainerHahnekamp Yesterday, I pulled the init branch and started the tutorial, and everything was OK. Today, when I launched the application with ng serve, the server started successfully, but when I go to localhost:4200, I only see the header and the page content is blank. After 5 seconds, I get a timeout. It's as if the frontend is trying to connect to a remote server without getting a response. I can send you a screenshot if you want.
@@RainerHahnekamp run the ap today and its ok
Can you share your vscode extensions?
Saleem, that's IntelliJ what I'm using. If you mean the inlay Hints, they are available in VSCode as well: code.visualstudio.com/docs/typescript/typescript-editing#_inlay-hints
very very good
Thanks!
Excellent video, but use dark theme please!
Hi, thank you very much. About the dark mode, is there a specific reason or just a matter of taste? I have been told that I should use light mode for that kind of presentations.
@@RainerHahnekamp Way easier/healthier on the eyes, especially if you, like me as a java-dev, spend 8 hours a day already behind a screen. We get recommanded to use dark mode with everything as much as possible (IntelliJ, Postman, Docker, Teams, ...). Almost every piece of software has a dark mode these days, and for a good reason. 🙂 In the end it is personal preference, but i can assure you, once you get used to dark mode, it is so much nicer to work, and your eyes will be thankful in the long run. Just think about your gps in your car, when it's nighttime, it also automatically switches to dark mode, seems strange, but that is because the contract is very tiring and unhealthy for your vision + alot of people watch youtube after their work or in the evening so when it is dark/getting darker. Hope this was helpful! 🙂 ps: please continue making great video's!
Do you have written this guide somewhere? Like in medium or some other place? Because audio on this is not so great and putting me off.
Hey, unfortunately no. What is the issue with the audio? I mean I know I am not a native speaker but microphone should be quite good.
Any other devs having knockout.js flashbacks?
Not me :). I skipped knockout.js and went to Angular straigt from ExtJs
Thanks for a great video! But could you please use dark theme next time? :D I'am watching it at the evening and my eyes are bleeding xD
Come on really 😅? To me it is the opposite. Every time I work with dark mode, I am almost blind.
I mean, if dark mode is better for the eyes or you and the other views have an easier time to read it, it is definitely an option. What I've found though, is the opposite: www.allaboutvision.com/digital-eye-strain/is-dark-mode-better-for-eyes/
I also remember that during the beginning of Covid, I got the recommendation to use light mode whenever I do a recording. If you more information, please let me know.
White theme...are you sirious?
Yes, I'm very "sidious" about it ;). Seriously, I work with light mode all the time. I try out the dark one, but only occasionally.
"You cannot be SERIOUSSSSDD"
I’m with you all the way. Team light-theme!
Nice thank you so much for the amazing content 🫡🙏👍
Thanks as well and you are very welcome Mahendra!
Thanks!
Thanks Jason.