Why I decided to switch to the inject() function in Angular

  Рет қаралды 54,627

Joshua Morony

Joshua Morony

Күн бұрын

My modern Angular course: angularstart.com/
Angular 14 gave us the ability to use the inject() function more generally in our projects, including replacing constructor based dependency injection. But is it a good idea to switch to it?
More on Dependency Injection: • Can AI explain the mos...
Get weekly content and tips exclusive to my newsletter: mobirony.ck.page/4a331b9076
Learn Angular with Ionic: ionicstart.com
#angular
- More tutorials: eliteionic.com
- Follow me on Twitter: / joshuamorony
0:00 Introduction
0:54 inject() benefits
1:53 Inheritance
4:05 The problem with inject()
5:36 Conclusion

Пікірлер: 182
@JoshuaMorony
@JoshuaMorony 11 ай бұрын
Join my mailing list for more exclusive content and access to the archive of my private tips of the week: mobirony.ck.page/4a331b9076
@DannyMcPfister
@DannyMcPfister Жыл бұрын
I’m a dirty filthy junior dev who loves Angular and I just have to say, your passion for Angular and your gift for explaining things has been a great addition for my day to day learning. You have a way for taking tricky concepts and packaging them together into easy to consume format and you do it with a positive energy. I appreciate your work and am always glad to see new Angular content from you pop up on my feed. Cheers!
@klirmio21
@klirmio21 11 ай бұрын
I’m a Junior dev with no experience so far and I do have to tell that inject is very clear and obvious, you understand right there that it is for “dependency injection” - it must be the default option to simplify angular for newcomers. I took me around 40 ministers to understand with the help of chat gpt the structure of a component and what exactly constructor did there, turns out it was used to simply inject a dependency which is a throw off in terms of the naming… I also tried vue previously as a framework and it’s very simple and really beginner friendly - but I’m glad I can just use inject and be cool
@MickR412
@MickR412 Жыл бұрын
Another two potential downsides of using the inject method in my opinion: 1. The dependencies are maybe a bit less obvious. All you add to look at was at the constructor arguments, every injected dependencies would be there. Now they could be scattered around the constructor arguments and defined properties above the constructor. Not necessarily a big problem but sometimes we can miss the big picture, especially in code reviews and if the class is big (which could be another problem in itself). I understand your point about younger developers and constructor arguments being less obvious that it's injected dependencies, but at the same time it's base Angular knowledge and should be assumed pretty early on. 2. When it comes to testing. If you are using a TestBed, it's pretty straightforward as nothing really changes. But it is not uncommon to write Isolated tests for pipes, directives or services (even components sometimes), when you are not testing in a TestBed environment, but are simply instantiating the class directly while providing the mocked dependencies directly in the constructors arguments. Now probably there are workarounds, like using _jest.mock('@angular/core', { inject: () => { ... } });_ or something like that (haven't tested), but that feels a bit dirtier and less "by the book". I see them very useful in the base/abstract classes use cases like you mentioned, or to create utility inject methods. For example if you want to inject a Store, then select a part of the store, you can create a custom inject function that abstract some things. const select = (stateSelector: Selector) => inject(Store).select(stateSelector); ... class MyComponent { private myState$ = select(MyState); } There are many cool ideas this potentially opens up! I'm just not convinced yet that we should get rid of any and all constructor parameters.
@JoshuaMorony
@JoshuaMorony Жыл бұрын
Good points, and yes the testing situation is something that does stick out - for me I always use TestBed anyway so it wasn't a concern, and I guess you could argue TestBed is the "default Angular way" to test, but yes I know a lot of people aren't using TestBed.
@gioelegentile
@gioelegentile Жыл бұрын
@@JoshuaMorony If you are not testing the DOM (which is a pain in the ass for everything jasmine/jest based) you don't really need TestBed, right? I think the best combination to test an angular app is spectator (to test everything which is not a component), cypress component testing (to test components in isolation), and cypress e2e (for full integration/e2e tests). What do you think about that?
@JoshuaMorony
@JoshuaMorony Жыл бұрын
@@gioelegentile I think there are lots of good ways to tests apps and your approach sounds great, for me I go with Jest/Cypress(for E2E)/TestBed. I am a bit biased toward what is the most "default" or "out of the box" since I do a lot of teaching, so I'll generally only reach for other libraries/tools if they are particularly obvious/compelling (e.g. I've obviously decided to switch to Jest/Cypress).
@alexandreroy5934
@alexandreroy5934 Жыл бұрын
​@@JoshuaMorony you should consider Testing Library, it don't change much the setup but it's way faster / cleaner to get DOM element and handle detect changes for us
@JohnWII
@JohnWII Жыл бұрын
Yeah #1 is the main reason why constructor injection is what we are sticking with. We basically equate the inject() style to normal Property Injection which is available in most modern languages with di frameworks and is often considered an anti pattern unless used explicitly for optional dependencies (which happens basically never for us). But of course a lot of this depends on your usage, muddying your dependencies like that in some little trivial app is all good.
@FauzulChowdhury
@FauzulChowdhury Жыл бұрын
Thank you for keeping us updated with the updates. Great use case demonstrated I have faced this issue with the super
@vredurs
@vredurs Жыл бұрын
Never stop producing content please, I think you are the Matt Pocock of Angular!
@piotrjarzabek-up9jc
@piotrjarzabek-up9jc Жыл бұрын
Perfect, this is very good solution for all base components :) great job
@ArchitecturalAesthetics2046
@ArchitecturalAesthetics2046 5 ай бұрын
very well explained. love this video.
@Thierry4Teen
@Thierry4Teen 25 күн бұрын
Well it's a nice information, starting Angular from v2 until v4 then switching to react it's the problem i've always faced when working with inheritance components, huge thank you
@chaos_monster
@chaos_monster Жыл бұрын
inject() is a service locator pattern and in many cases it get's easy to fall into anti pattern. So be aware what you teach. But I must admit the use-case for inheritance can be considered useful, especially when you go with mixins instead of classical inheritance.
@JoshuaMorony
@JoshuaMorony Жыл бұрын
I've seen this criticism but haven't seen any examples yet of where this distinction might matter (not saying they don't exist, just something I haven't come across yet) - do you have an example of an anti-pattern you think inject() might encourage?
@chaos_monster
@chaos_monster Жыл бұрын
@@JoshuaMorony Basically the entire argument about the service locator pattern being an anti-pattern evolves around testing. The most "common" situation I've encountered is when you use inject() in another function that encapsulates some behaviour. Those functions are hard to test and even harder to mock.
@JoshuaMorony
@JoshuaMorony Жыл бұрын
@@chaos_monster thanks - personally I have no intention to do anything fancy with inject() and will just use it as a direct replacement for constructor based injection, but certainly the ability is there to do some trickier things (especially for library authors) that we haven't been able to experiment with (and I guess potentially get burned by) yet
@EricPhillips89
@EricPhillips89 Жыл бұрын
I don't mind the inject() keyword, but I think the runInInjectionContext method is problematic-- that is where we start to fall heavily into the anti-pattern.
@toxaq
@toxaq Жыл бұрын
Would use it for the inheritance example but otherwise stick with constructor injection. I like knowing all the dependencies in one spot.
@julienwickramatunga7338
@julienwickramatunga7338 Жыл бұрын
Thank you for the pros and cons, nicely explained. For your poll: +1 for the inject( ) team, I already use it and I like it.
@AlainBoudard
@AlainBoudard Жыл бұрын
Excellent argument for inject function Josh ! I have a few examples in mind of codebase with inheritance and this switch will indded be welcome !
@ali-celebi
@ali-celebi Жыл бұрын
Great video, as usual :)
@JeetuChoudhary001
@JeetuChoudhary001 Жыл бұрын
Awesome. Definitely will switch
@ShaharHarshuv
@ShaharHarshuv Жыл бұрын
Thanks for this video, will help me convince my team
@ZuravvskiIT
@ZuravvskiIT Жыл бұрын
Just in time Joshua! Yesterday, I came to the same conclusion whilst refactoring old routing guards.
@Blafasel3
@Blafasel3 Жыл бұрын
Considering many other DI frameworks tried similiar techniques to the inject function and backed off it again (e.g. Spring Boot @Autowired which is essentially the same thing) and are encouraging constructor injection again. I don't like the turn the Angular team took by the inject function, but I see why people would like it. It feels like a shortcut to me and shortcuts tend to encourage anti patterns ;)
@mfpears
@mfpears Жыл бұрын
The only question I care about is, why? There are many things about Java that might make sense in other contexts but definitely suck in front and stuff
@Blafasel3
@Blafasel3 Жыл бұрын
@mikepearsonengineering8793 with the annotations like autowired or functions like inject it's easily possible to instantiate a class with null fields and running into compile time npes. With constructor injection it's not. Another thing, it's a little harder to realise that your class has too many dependencies since they are not bundled in the constructor but instead are cluttered around the class. I have seen epic classes with 15 dependencies cluttered between methods and other fields.
@vishalsharma33
@vishalsharma33 Жыл бұрын
One of the reasons why I still like XML based Injections in spring over annotations. Where I have clarity on how many Resources are being Injected by looking at the xml configurations
@romanstejskal4529
@romanstejskal4529 11 ай бұрын
Java is a different beast compared to JavaScript. TypeScript has to do some extra work and emit additional code to allow constructor injection to work at all, this as well as decorators are non-standard extra layers on top of the runtime, you could say they are workarounds. The inject function is just pure JavaScript and doesn't need any additional transformation or runtime information to work. inject really is just what context is in React/Svelte/Vue, and I think it makes a lot more sense in the JS/TS world.
@GLawSomnia
@GLawSomnia Жыл бұрын
Damn you surprised me, i was sure that todays video will be about the Signals RFC :D But I myself am used to DI from developing BE (spring), so both ways are good for me. I do like the inject function though, opens up quite a few simplifications like functional guards and resolvers 😁
@HassanRaza-ym3uf
@HassanRaza-ym3uf Жыл бұрын
Going to start using it right now
@CraigShearer
@CraigShearer Жыл бұрын
Some good ideas here. I've mostly continued to use constructor injection, mainly through inertia, though have made good use of inject() in inheritance hierarchies. I guess it takes some discipline to structure code so that all the dependencies are declared together - which isn't quite as cohesive as having them declared as parameters to a constructor.
@HackHeyner
@HackHeyner Жыл бұрын
This is MAGICAL!!
@PatricioHondagneuRoig
@PatricioHondagneuRoig Жыл бұрын
I hope this is expanded to inputs, outputs, and all other class member decorators eventually!
@JimmiJohnJunnior
@JimmiJohnJunnior Жыл бұрын
You can also inject inside routes (title, can activate,resolve etc..) which I can't think how else you could with a constructor.. Btw, now that standalone components are out you could redo your angular code structure video to address the removal of the routing module as a shell feature since all you need is an extra routes file now. 🥂
@EER0000
@EER0000 Жыл бұрын
Some people are saying that inject is a magic keyword, but I would argue that dependency injection is equally magic, just some different syntactic sugar. I can see the advantages in case of inheritance, but in the apps I work on this rarely happens. After watching the video I got excited about using inject, but then I thought about it some more and I think I'll stick with DI in the constructor (mostly because I like the syntax better)
@yuriinadilnyi3029
@yuriinadilnyi3029 Жыл бұрын
great tuts
@JozefRzadkosz
@JozefRzadkosz Ай бұрын
What is your IDE? Great video tbh, the way how you explain things is amazing, your voice doesn't make you tired of listening, keep doing this we need you! :D
@JoshuaMorony
@JoshuaMorony Ай бұрын
Thanks and I'm using neovim
@nickramsey6498
@nickramsey6498 Жыл бұрын
If you want a balanced mix, only ever DI the Injector service given by Angular. Then super the injector to the base component. The base class can then use the injector service to get the required services. Meaning you can add new injections to the base without needing to update all components inheriting the base.
@MrBloodWoork
@MrBloodWoork Жыл бұрын
I switched to inject and I love it, no regrets at all! :)
@teckasm
@teckasm 10 ай бұрын
Makes usage with the occasional, unavoidable inheritance much nicer.
@eliotistube
@eliotistube Жыл бұрын
I made this transition months ago in four different projects, no problems!
@mehdimahmud5191
@mehdimahmud5191 8 ай бұрын
thank you for th calrification. Just one thing. how do we use the services inside spec for testing?
@yousafraza7747
@yousafraza7747 Жыл бұрын
Hey, can you make a video on zoneless change detection. Would really help
@o_glethorpe
@o_glethorpe Жыл бұрын
Will stick with the constructor approach.
@antoniopekeljevic9931
@antoniopekeljevic9931 Жыл бұрын
This is so neat. I don't know why Angular doesn't mention it as an option in the Dependency Injection documentation page.
@Matrium0
@Matrium0 Жыл бұрын
This is a hard one for. Coming from a Java/Spring World, where basically everyone started with setter injection and switched to constructor injection it's hard to bring me to "switch back". I personally ran into the problem you described (with inheritance and having to change the super() call in every component), so I'll certainly switch to inject() for THOSE cases at least after this video
@Matrium0
@Matrium0 Жыл бұрын
To expand on this. Now that I think about it, I believe the reason why that movement happened in string, was because setter injection was always a bit akward there. It happened at an undefined time after construction, so you could not use the injected services in the constructor and such. So a @PostConstruct hook was mostly used for stuff that actually "should have been in the constructor, but couldn't, due to setter injection". Constructor injection fixed THAT + made sure that you can't construct classes with only half their dependencies. This is mostly relevant for testing, though I can imagine this point could be true for Angular as well. The first (and more important) point isn't though, so there is a strong case for inject()
@endlacer
@endlacer Жыл бұрын
Do you see any problem with mixing these two approches? In our codebase we have the case, that we would have a circular dependency, cause two services depend on one other (one mostly on on the other, but the other uses a variable of the one). so that would be a circualr dependency. We solved that by using the inject method inline for just this service to get the property. No CircularDependencyError. So would that be a disadvantage? Angular not detecting circular dependencies?
@PieJee1
@PieJee1 Жыл бұрын
The only benefit i can think of is some services that require heavy initialisation code that is only useful when you do an action in your application. I noticed dependency injection in the constructor is in particular more liked by backend developers then frontend developers
@jordisarrato331
@jordisarrato331 Жыл бұрын
I have this exact same case where i have to import a serviceA in the ComponentA for inherence, i'll try this but im in angular 13, i have to see if it works.
@AbnerJuarez97
@AbnerJuarez97 Жыл бұрын
What about creating a decorator to do this same as well?
@emesen_
@emesen_ Жыл бұрын
How about 'private' constructor injections? Can the inject() approach replace the those? Like. Is a private variable deceleration for an inject(service) as private as when declared private in a constructor injection?
@GerZah
@GerZah Жыл бұрын
I stumbled across exactly that just recently - thanks for the clarification! Question, though: How does this affect unit testing, im my case with jest? Can I provide mocked dependency injections for these `inject(…)` statements just like I would have for the `constructor()` injections?
@ashmcconnell3868
@ashmcconnell3868 Жыл бұрын
Was wondering this too. I tend to avoid TestBed as I found it clunky and provide my own mocks when unit testing. I like this inject() style, but I'm not sure how it would work with our unit testing conventions.
@aleksandarbudic6462
@aleksandarbudic6462 6 ай бұрын
How often do you do component inheritance in Angular? I avoid it like the plague (inheritance) in general. I don't think I've ever used in for components in Angular.
@NickTsitlakidis
@NickTsitlakidis Жыл бұрын
I'm not sure if it was mentioned in another comment, but there is another downside which doesn't have to do with technical limitations or ease of coding. And that's the meaning of the constructor. If we see this from a strict OOP standpoint, the constructor of the object should be the point where you pass the object dependencies and where your object is instantiated based on these dependencies. That's the whole meaning of the function. So if you pass object dependencies to the object using the inject() method, essentially you ignore what the constructor is meant to do and you hide this "logic" somewhere else. Not a great deal for any dev who doesn't care about OOP "theory" but it's worth mentioning because consistency and best practices are important in large projects. To be clear, I'm not saying that inject() is a mistake, it makes sense for functional cases (guards for example), but if you're in the OOP context, I think it's not the right option.
@holger3526
@holger3526 Жыл бұрын
Let's see it other way around: in case all classes are using the exact same service the base class does, inject is the way to handle it like a standard property of the base class, so the others don't need to care. If you need different services to inject, depending on the class you use, do it the constructor way. So everything will be OOP.
@NickTsitlakidis
@NickTsitlakidis Жыл бұрын
@@holger3526 I can see why such a case would make the usage of a base class easier. It still doesn't change the fact that you hide a possibly important dependency though. Think of it another way, how would this class work if a developer tried to use it without Angular? If all the dependencies are in the constructor, it's clear what you need to do. If they are not and you don't have Angular doing its magic, then you'll have to know that you need to set this dependency some other way. It's also understandable to think that working without Angular's DI won't make sense for your case. But personally if I can make a class easier to move to another project/context/whatever, I prefer doing that.
@holger3526
@holger3526 Жыл бұрын
@@NickTsitlakidis I don't see this. If you are trying to use Angular style somewhere else, it won't work. But there are Inject decorators in other languages too, like Spring. So you always need to be aware of this. But you can also use it this way: Define the service in the class and set it using inject function inside the constructor. Maybe this is more obvious then.
@NickTsitlakidis
@NickTsitlakidis Жыл бұрын
@@holger3526 What is the benefit of using the inject function inside the constructor? To avoid having a lot of parameters? If so, maybe we're focusing on the wrong thing. A class with many dependencies should probably be refactored because it does more than one thing. I would argue that having the parameters in the constructor makes this even more obvious for the dev to refactor it. Regarding your comment about using the class somewhere else, a well designed angular service is basically a simple TS class with the Injectable decorator. If that's all you use from Angular then it's easy to migrate this class to another project. To compare this with Spring (although it's been some time since I've used it), I would make a Bean function for the service I want to provide, and the service class would be clear of annotations if possible.
@holger3526
@holger3526 Жыл бұрын
@@NickTsitlakidis it's not "just" having a lot of parameters. I faced the problem a couple of years and it was like told here: every class extending the base needs to link and inject the exact same service. This is going to become a nightmare when you need to change the base, like adding a new service. In this case every child needs to do the same too. And now think about micro frontends where you aren't able to update everything. In this case your stuff will crash.
@RobertKing
@RobertKing Жыл бұрын
I also prefer composition to inheritance. none the less, my project has an area with lots of inheritance, however, none of it is within the injection context, so i gotta call super with all the services. One thing I considered was creating a ctx object that gets passed to super each time with all the services. This is a similar problem to prop drilling though. In the end i just call super everywhere with the services, not too bad.
@mystyani
@mystyani 8 ай бұрын
for the longest time i used the constructor DI and inheritance but i realized sooner than later with new requirements it makes a hell of editing cycle so i switched to the inject() but using some backdoor way that allows injecting in ngoninit and so on by making custom AppInjector that gets injected in AppModule, that way it will be available to use whenever you need instead of constructor context too. I don't understand perfectly why angular team didn't include this approach to be in their default injector, mostly something that has to do with lazy loaded modules/services and TreeShaking builds yet i find it very solid for most use cases. SO in short HELL YES I AM WITH THE inject(service); to hell with constructor injection unless if you are forced to for some reason. Or to be reasonable a mix and match might make sense in some cases when you need to make sure that who ever is extending your class knows it's a must to have these services. lot's of other frameworks stayed on the constructor injection and i do believe it's one of the reasons for that.
@titusfx
@titusfx Жыл бұрын
The video started saying that is better for juniors to see inject so they can see what's going on, and then automatically is criticising the use is super explicitly adding all the dependencies(which it will hide for junior the behaviour). And worst is magic, because inject is working there as a decorator, in order to be able to inject those things. There's a reason of explicity telling things to another dev. I believe that inject on constructor is cleaner because you can use the same idea with other injectors. If you want to reuse those classes in whatever place outside angular, it will still work. Also, you will know explicitly what classes depends and you can use it event without a fancy injector.
@FraserMcLean81
@FraserMcLean81 Жыл бұрын
As C# backend developer, I prefer constructor based injection
@merlinwarage
@merlinwarage 11 ай бұрын
Because that's the proper way.
@r-naotwo6290
@r-naotwo6290 Жыл бұрын
Does it work with ActivatedRoute?
@clashclan4739
@clashclan4739 11 ай бұрын
That adding removing in baseclass could break on runtime than compile time like constructor injection
@jaybee6382
@jaybee6382 11 ай бұрын
What about for unit testing?
@danilobassi9045
@danilobassi9045 Жыл бұрын
What about conditional injection?
@zikkrype
@zikkrype 3 ай бұрын
I like point with BaseComponent
@danielguzman8607
@danielguzman8607 Ай бұрын
I just hate having a lot of dependencies inside constructur(), I looks quite ugly and kinda annoying for me, and also hate the super() (specially with many dependencies), so you just convinced. I'm switching to it. Thanks!
@JakeAndDaddy
@JakeAndDaddy 12 күн бұрын
You had me sold on not needing to mess away with child classes. Does it still work ok with factory methods? The only thing I’d add is making the injectable read only. I do that on the constructor version
@JohnConnorTM
@JohnConnorTM 6 ай бұрын
I primarily see its advantage for base classes, not sure the esthetics of it bothers me either way. Thanks for an informative video!
@TayambaMwanza
@TayambaMwanza Жыл бұрын
The writing on the wall for constructor for me was when Minko Gechev used it while teaching Ryan Carniato Angular. I don't think constructor based injection can even disappear though because it's part of js classes so if you want to use it you can and I don't think it will be deprecated it would take more effort than it's worth to disable it.
@hammamboutafant3659
@hammamboutafant3659 Жыл бұрын
I think it's like @Autowired on Spring, not recommended for several versions but it's still there
@rumble1925
@rumble1925 Жыл бұрын
It's not part of js classes by default. Angular holds the references and injects them
@TayambaMwanza
@TayambaMwanza Жыл бұрын
@@rumble1925 I meant the constructor itself, if constructor is nothing special in js syntax you could easily see both co-existing.
@rumble1925
@rumble1925 Жыл бұрын
@@TayambaMwanza Oh alright I misunderstood
@CaseAhr
@CaseAhr Жыл бұрын
Josh -- Your email that went out had mismatched text to go with the video link. Just FYI.
@JoshuaMorony
@JoshuaMorony Жыл бұрын
Thanks, I didn't even notice! I'll pin this for anyone confused, the service with a signal video will be next week's video!
@Billiam112
@Billiam112 Жыл бұрын
What about when you have @Optional() or @SkipSelf() etc? You'd still to do that via the constructor, or? I'm sticking (and liking) the constructor way (although not having to pass them when inheriting seems niiiiiice...) :)
@JoshuaMorony
@JoshuaMorony Жыл бұрын
You can optionally pass InjectOptions to the inject() function which allows you to provide skipSelf etc.
@Billiam112
@Billiam112 Жыл бұрын
@@JoshuaMorony Oh okay, thanks for lettig me know. :)
@marekk9008
@marekk9008 Жыл бұрын
I think I'll use inject function mostly in cases when I want to extract some logic to outside the class. But I wonder how to test something like this 🤔 I think I will continue using constructors by default to be consistent with the rest of my codebase
@JoshuaMorony
@JoshuaMorony Жыл бұрын
I think you will have to use TestBed, which wasn't a concern for me as its what I always use anyway
@chaos_monster
@chaos_monster Жыл бұрын
This is the perfect example of the service locator pattern being an anti-pattern. Thank you 🤗
@3htomit
@3htomit Жыл бұрын
Josh, Thanks a lot for your video. After watching your video I wanted to try the inject() method. I struggle with the token injection, such as: constructor( @Inject(FEATURE_TRANSLOCO_SCOPE) private readonly _scope: ProviderScope, ) {} When I replace it by: private readonly injectedScope = inject(ProviderScope); I get the following error from my IDE: TS2693: 'ProviderScope' only refers to a type, but is being used as a value here.
@3htomit
@3htomit Жыл бұрын
I found the solution for the token injection: private readonly injectedScope: ProviderScope = inject(FEATURE_TRANSLOCO_SCOPE);
@manit77
@manit77 6 ай бұрын
inject (Location) throws an error inside a component of a component hard to track down.
@kumailn7662
@kumailn7662 Жыл бұрын
True, I always annoyed with lots of parameters in constructor!!
@cipherxen2
@cipherxen2 8 ай бұрын
A better option would be to use annotations. Like @Autowired in spring.
@merlinwarage
@merlinwarage 11 ай бұрын
If you don't need the dependencies / different instances, use abstract class.
Жыл бұрын
what about the decorators @skipSelf and the others? Anyway inject its nice to avoid inheritance
@JoshuaMorony
@JoshuaMorony Жыл бұрын
You can still optionally provide InjectOptions to the inject function where you can specify skipSelf etc.
@mattlaw4395
@mattlaw4395 Жыл бұрын
Personally prefer constructor based injection. The inject function just looks “hacky” maybe because I’ve been to used to the old ways. Main concern either way is the constructor gives you a single source of truth. Injects can be added on like 6 or on line 100 and yes it’s up to developers to be smart about it but at least the constructor enforced the pattern :) anyways have used it for factory’s so it deffo is in my toolbox
@oleggranevskij6872
@oleggranevskij6872 Жыл бұрын
But how often you use inheritance? 2 times in 1 year? Is this so big problem add super() and have contructor order if its so rare? How you will construct isolated component for unit testing?
@JoshuaMorony
@JoshuaMorony Жыл бұрын
Some people might use it more heavily, but for me the inheritance problem was just a small added bonus - mostly I see the two approaches as being pretty equivalent, I mostly just think inject() is nicer from a syntax/DX point of view. As for testing, I use TestBed anyway so it isn't a problem but yes this would be a factor for people who want to create tests by passing deps through the constructor
@oleggranevskij6872
@oleggranevskij6872 Жыл бұрын
@@JoshuaMorony also you know compound components pattern? Following this concept its possible inject parent component into child bus also child can live without parent, in that case we use @Optional decorator on dependency in constructor (also in some cases build will be smaller). Injecting in that way we cant use decoraters anymore i guess, right?
@dimitritsikaridze6220
@dimitritsikaridze6220 Жыл бұрын
show us your neovim config
@johangustafsson6121
@johangustafsson6121 Жыл бұрын
The convention in many frameworks for many languages is that dependencies are provided in the constructor, this breaks that pattern. "feels nicer" is not a strong enough argument for changing that IMO. The times we (my company) extended components like in your example is so rare that it's not a strong argument for it either. Convention or "we always do it this way" is in itself not really a strong argument, but the reason for change is neither.
@jasonrooney1368
@jasonrooney1368 Жыл бұрын
Define many frameworks and many languages? You do realize you're working with a web framework here? Vue - inject() React - useContext() Qwik - useContext() Solid - useContext() Svelte - getContext() Angular was the only one doing constructor based dependency injection since it's the only one still clinging to OOP concepts. This is a move towards a more functional and composable approach. I'd wager we'll see an alternative to Class components very soon.
@johangustafsson6121
@johangustafsson6121 Жыл бұрын
@@jasonrooney1368 Perhaps, perhaps not. For now, I consider it to be more of a bike shedding problem than anything else, having two different ways of doing the same thing just introduces unnecessary friction, in the class and when testing. One of the things I appreciate working on many different teams is the consistency and similarities between projects that comes from using Angular.
@lightyagami5963
@lightyagami5963 2 ай бұрын
the injector function would work for the lazy injection places where inject function thorws error.
@yaibanoutsukushii
@yaibanoutsukushii 11 ай бұрын
huhu I've got a question and would love if someone could answer. So I do prefer using the inject function, but I run into the following problem: I mostly want to have the injected Services private as there is no need for accessing them outside of the component. And I mostly want to use the declerative approach and make my members constants. So it would look like this: public readonly someObservable$ = someService.doSomething$(); private readonly someService = inject(someService); this code obviously fails as I use the service before I declare it. But if I move the service up, then I have the problem with eslint and member ordering; it says that private members are to be declared after the public ones. I wonder, how can we fix this problem? I can of course just ignore the tslint rule for this case but is this the best practice?
@JoshuaMorony
@JoshuaMorony 11 ай бұрын
I've been using private fields to deal with this (e.g. #someService = ....) this makes it private (and also has the side benefit of being enforced at run time but I don't really care so much about that) and ESLint won't complain about the ordering.
@yaibanoutsukushii
@yaibanoutsukushii 10 ай бұрын
@@JoshuaMorony hey only saw it now, thank you I'll try it out!
@ucnguyenphanhuynh3134
@ucnguyenphanhuynh3134 10 күн бұрын
good
@arturkalbukov6856
@arturkalbukov6856 Жыл бұрын
inject crate new instance of service? and you can't share data between 2 component?
@chaos_monster
@chaos_monster Жыл бұрын
No the singleton pattern is not affected by the inject function. It behaves the same way it does with the constructor based Dependency injection
@LarsRyeJeppesen
@LarsRyeJeppesen Жыл бұрын
No, same instance. You can share
@josecarloss.a.tissei4841
@josecarloss.a.tissei4841 Жыл бұрын
The inject function is basically a service locator wich is an anti-pattern, there's a lot of content online from people a lot smarter than me explaining why we shouldn't use service locators
@yuriblanc8446
@yuriblanc8446 Жыл бұрын
service locator pattern hides the implementation and introduce DI concept in the class dependecies. For instance to test a class using inject() would only work using the container or you should be able mock or stub the inject function, while in constructors can work also outside Angular as long as you dependency's are proxy's. (ex a proxy to httpclient type ) It's nothing new, most of the time it's much better to use constructor injections because inject pattern risks seems unharmful but delivers coupled code to the injector. also when using a function using internally inject... why not pass the dependency to the function argument instead? it's bad, maybe looks cool but I only see drawbacks especially in large codebases where many people working on it with various expertise levels..
@flavioarantesdoamorimbarce95
@flavioarantesdoamorimbarce95 Жыл бұрын
I’ll stick to constructor for now. I’m working on a angular 12 project 😢
@LarsRyeJeppesen
@LarsRyeJeppesen Жыл бұрын
Why 12?
@PeterKlausSchmelzer
@PeterKlausSchmelzer Жыл бұрын
It doesnt look nicer.. but.. the inheritence issue is a valid argument to give this a try.. gj, tx for the explonation..
@j4nch
@j4nch Жыл бұрын
I must say, I'm not agreeing with you on this one. I find the constructor a nice a easy to find point of entry for the component and it's easy to see what is injected and what is created/managed only in my component(well, the components of the colleagues). And from an architecture standpoind, I love the concept of saying: Okay, that service is required to build this component, and you cannot instantiate it without providing an implementation.
@ancientelevator9
@ancientelevator9 Жыл бұрын
Angular noob here ...I recently switched to: constructor(private categoriesService: CategoriesService){ from: private categoriesService: CategoriesService constructor(private categoriesService: CategoriesService){ this.categoriesService = categoriesService } lol, it also feels weird to me that I am putting stuff in a constructor, but I am not instantiating the objects (Angular is)... So I don't actually pass these services to the constructor
@danielzaiser
@danielzaiser Жыл бұрын
inject function looks cool, it's an angular 14 feature, we still use angular 12 at work. but i'll be sure to use it in the future, thank you for the showcase :)
@nathanalberg
@nathanalberg Жыл бұрын
i've liked the inject change... plus.... you missed the bonus fact that they can be used inside FUNCTIONS.. which dont have constructors... (like functional guards)
@merlinwarage
@merlinwarage 11 ай бұрын
Yeah. and readability, design patterns and other small things are overrated anyway.
@alan614
@alan614 Жыл бұрын
Using the inject function in the context of extending a BaseComponent seems huge! So many constructors used where I only did `super()` lol. This is great :D
@40fps143
@40fps143 Жыл бұрын
What IDE is that ?
@JoshuaMorony
@JoshuaMorony Жыл бұрын
It's neovim, using this config: github.com/joshuamorony/nvim
@cosmokenney
@cosmokenney Жыл бұрын
Seems more declarative to me. I kind of like it.
@kumailn7662
@kumailn7662 Жыл бұрын
sort of a @autowire in sprinboot
@JoshuaStringfellow1
@JoshuaStringfellow1 Жыл бұрын
Funny/interesting that Spring Framework has shifted from field injection to constructor injection and Angular might be doing the opposite.
@merlinwarage
@merlinwarage 11 ай бұрын
Angular doesn't do the opposite. Some people think that injecting above the constructor is the way to go due to lack of OOP knowledge.
@JoshuaStringfellow1
@JoshuaStringfellow1 11 ай бұрын
@@merlinwarage Angular is certainly embracing field injection, documenting it in their latest First Angular App tutorial and Learning Angular youtube series.
@andrelouw2677
@andrelouw2677 Жыл бұрын
I was hoping it was a way around circular injection problems.... but alas😢
@stormie9489
@stormie9489 Жыл бұрын
Exactly to the point. Not just in Angular but NestJs, we also switch to inject() function. It's boost our develop experience as we can take advanced of OOP.
@lassehamborg7209
@lassehamborg7209 Жыл бұрын
How do you determine if the injection is private or public? (tbh, I don't know any usecases for public but it seems like a difference between the two.)
@JoshuaMorony
@JoshuaMorony Жыл бұрын
It's public by default, if you want to make that explicit you just prefix with public just like in the constructor, or if you want it to be only accessible to the class you prefix with private, if you explicitly want the class and the template to be able to access it but nothing outside then you can use protected
@donwald3436
@donwald3436 Ай бұрын
lol other DI frameworks switched from field injection to constructor injection to prevent missing dependencies.
@Nightbanger89
@Nightbanger89 Жыл бұрын
A way to "inject" some service inside the ngOnInit would be to inject the Injector first and then using that in ngOnInit. But prob not the best idea 😂
@DenisEneotescu
@DenisEneotescu Жыл бұрын
for those working with Angular and Spring, isn't this the same idea used by @Autowired for fields?
@adambickford8720
@adambickford8720 Жыл бұрын
100%. i'm kinda surprised to see a known antipattern promoted like this.
@rened.lacruzibarra5974
@rened.lacruzibarra5974 Жыл бұрын
@@adambickford8720 the good pattern is use constructors instead of autowired ?
@adambickford8720
@adambickford8720 Жыл бұрын
@@rened.lacruzibarra5974 Really just a constructor, no annotations required. Spring will infer the types and supply them automatically by looking at the available factories. Then you use lombok to generate the constructors so it *looks* like field injection again lol! But now your core logic is completely isolated from your container. This really helps in testing, evolving, aggregating/composing, etc. The container is for keeping your business code isolated from the 'real world' concerns (I/O and all the issues that come with it).
@dayronalfaro9461
@dayronalfaro9461 Жыл бұрын
Yes I will Switch jeje is more simple
@razt3757
@razt3757 Жыл бұрын
This is a bad idea. IMO. The reason injections are done through constructors by default is because it's impossible to miss an injections while constructing the service by hand, for example when testing. Property injection is a bit of an anti pattern because of that, as many have already pointed out in the comments. People have tried to use property injections in Java for a long time, and to be fair, Java developers had an even more convincing reason: Java constructors can't promote constructor parameters directly to class properties, like you can in TS or other languages. You would have to manually assign them the old way: this.myProp1 = myProp1. But even that was not convincing enough because nobody uses prop injection anymore, or at least they shouldn't.
@theanswer1993
@theanswer1993 Жыл бұрын
I changed to it as soon as I saw that Brandon R. used it in one of his live streams. Angular should really update their docs and tutorial to use this instead of constructor cause it's so much clearner and easier to write
@JoshuaMorony
@JoshuaMorony Жыл бұрын
I like the idea of just doing whatever Brandon does, this is a good strategy
@HagbardCelineOnRust
@HagbardCelineOnRust Жыл бұрын
inject(UpvoteService)
@JOELJOSEPHCHALAKUDY
@JOELJOSEPHCHALAKUDY Жыл бұрын
Nope , definitely not for me from my experience. I understand your intention, but I would still recommend sticking with the regular Angular DI pattern. I have been working with Angular since AngularJs and have been mentoring the Angular community on different projects through all versions up to the latest. The default pattern works great, is stable, and has been industry-proven and trusted by the community. Although Angular as a framework has added new options to attract React developers, I don't think that the Angular community, who have been using the framework for a long time, will appreciate if the framework tries to be another React. The trend of trying to 'React'ify Angular goes against the established Angular patterns and will create clutter for the community. One of the things that I love about Angular is that everything works and there are no 1000 ways to do the same thing. I understand that there is a new trend of trying to make Angular more like React, but from my experience, that is the wrong way to use Angular (although no one is stopping you from doing it). One advantage that I have found when working with Angular over the years is that there is a clear defined way to do everything. This makes things easy to maintain. For large teams with a lot of developers with different experiences working to build an enterprise application, this kind of organized way of doing things makes everything easy to scale, modify, and maintain. For example, if you are a frontend developer who has worked in Angular and React across different projects, even if you change to a different company, the pattern for Angular will remain the same, making it easy to understand and maintain. However, in the case of React, each and every developer/team/company has their way of doing things, resulting in 1000 ways of doing the same thing. Trust me, it's too cluttered. There is even a joke about it among the developers I know: "My way of using ReactJS is unique to me and differs from yours." Well, they are all right, but that is the problem itself. The above well-defined way of doing things made Angular popular among enterprise software development. I would also like to know what others in Angular community thinks about this. So, I invite you to share your video here: facebook.com/groups/angular.developers.community/"
@sebuzz17
@sebuzz17 Жыл бұрын
I actually don't like this trend for 2 reasons : 1. In this example, it is far from obvious that you can use "history" or "username" in your component, and you might simply inject it again not knowing that you have access to these properties from the BaseComponent class directly, especially if someone else arrive in your project later and don't know how things were set up this way. If you stick to the constructor method, you'll get an error which is a good thing to remind you what the BaseComponent class needs (and offer in exchange). 2. When you use a constructor, you can refer to this part of the component to check all the dependencies in one and only one place. Using the inject function, your dependency can be declared anywhere in your code (as long as it's been declared in the class scope and not in a function as you've shown). There are probably other use cases where the inject function can be neat, but i'll stick with the constructor injection in component and services to make sure my team doesn't make my code a hell to read.
@rujor
@rujor Жыл бұрын
I'll probably go with the inject function eventually too. BUT... I don't agree that it looks nicer. Firstly, it feels unfamiliar to call a function providing a type as an argument--not something I usually do. Secondly, you call a 🪄magical built-in function that you have to understand the real underlying purpose of (including the reasons presented in this video) to appreciate. That's unfamiliar because, at least to me, Angular is heavily "this.functionName"-based (I guess you're more of the functional programming-type school though). Frankly, it just feels perfectly natural to pass dependencies to a class by its constructor, not by using an internal function call (honestly I can't come up with any other examples where I'd do it this way). That's currently my take 🤷‍♂.
@omarkarim9298
@omarkarim9298 Жыл бұрын
You can achieve the same thing by using a static class with a reference to the main injectors from the module classes
Why didn't the Angular team just use RxJS instead of Signals?
8:15
Joshua Morony
Рет қаралды 88 М.
The easier way to code Angular apps
9:54
Joshua Morony
Рет қаралды 64 М.
КАРМАНЧИК 2 СЕЗОН 7 СЕРИЯ ФИНАЛ
21:37
Inter Production
Рет қаралды 533 М.
Incredible magic 🤯✨
00:53
America's Got Talent
Рет қаралды 65 МЛН
버블티로 체감되는 요즘 물가
00:16
진영민yeongmin
Рет қаралды 117 МЛН
Angular Inject Function - Better Than Constructor
8:10
Monsterlessons Academy
Рет қаралды 11 М.
ThePrimeagen Hacks My Productivity
3:30
Scott Macchia
Рет қаралды 41 М.
Why Angular Signals? Write Your First Signal
14:25
Angular University
Рет қаралды 7 М.
I only ever use *these* RxJS operators to code reactively
25:25
Joshua Morony
Рет қаралды 122 М.
Build Generalized DRY Angular Code with Generics
14:44
Deborah Kurata
Рет қаралды 6 М.
The Flaws of Inheritance
10:01
CodeAesthetic
Рет қаралды 908 М.
Angular is about to get its most IMPORTANT change in a long time...
10:15
ngTemplateOutlet is WAY more useful than I realised
16:36
Joshua Morony
Рет қаралды 73 М.
Angular Signals: What? Why? and How?
27:08
Deborah Kurata
Рет қаралды 54 М.
КАРМАНЧИК 2 СЕЗОН 7 СЕРИЯ ФИНАЛ
21:37
Inter Production
Рет қаралды 533 М.