@@meolivares06 hi :) of course you can. You can buy it as usually and your local currency will be automatically converted during the purchase to Euro with a current exchange rate.
Hi!! Your videos are great as always, for the last 2 weeks I been trying to buy one of your courses (Advance forms), but I cant buy it, my card is being declined every time, I dont know why if already bought one of your courses before and I dont think its a problem with my bank, Im always buying stuff from internet xd
Can you help me please? I can't bind Custom Control to emitEvent: false; I use Custom Control, but i need to "correct" some of inputs. So when user input smth - i can alter it, with setValue(value, {emitEvent:false}). It works with normal forms, but with Custom Form Control i read that updateValueAndValidity used ignoring "emitEvent" option with Custom Control. So what to do, to make emitEvent: false work? Or what method use, to replace it?
Good little dive into intervals - the ControlContainer, but honestly, it looks like you are on your way to reinvent the wheel - namely the template driven forms
Hi Dmitry, I am really glad to hear your opinion, thank you 🙌 indeed, the inspiration for self-registered form control models I found in Template-Driven forms :) I know that with TDF it would be even easier to reuse the controls since the control registration happens there automatically but sometimes we just have to stick with reactive forms.
Since this video came out I used this approach in two projects and I really love it. One thing that is missing for pretty much all dynamic form videos, tutorials and courses is to be able to dynamically hide or show a control based on another ones value. If you happen to know a solid solution for that, please make a video or add it to your course. In your course you already have a section about creating a form based on a json, but no way of adding conditions for visibility. I found a working solution, but it relies on mutability. For those wondering: I'm using a signal to hold the config of the form which includes a visibility state as well as conditions on when to show certain fields. Then I'm building a form based on that condition using the approach from this video. That way we can keep markup and from group in sync. Then I'm listening to value changes on the form group and look for any controls that might need to be updated. I then set their visibility to either true or false. However, since my config can be deeply nested I'm extracting all controls, that dependent on a another one, into a computed signal. I use this as a base to find controls to check and modify.
Thanks for the great tutorial. I have been trying to do this cleanly for a long time ! Would be interesting to have some testing strategies for the subform component, as it needs to be part of a encapsulating formgroup to be functionnal.
Nice approach, thanks, will definitely use in our project! How do you deal with the fact that nested part is invisible when inspecting a form declaration in the parent component, do you usually check the template as well?
this is a good question. I think you should look always for some balance. For example, how much I will win if apply this technique for a simple login form? Well, probably not too much, right? It will bring too much magic to your forms. But maybe if it is a complex piece of logic that would require a lot of boilerplate, validation logic, etc. Then probably a bit of magic isn't so bad 😊 Also, you can use only part of the whole pattern (providing only ControlContainer) and keep separately form models and the view if you want/need.
Interesting approach, previously in such cases I used Control value accessor. I think this has one advantage, we can keep the model reference in the main form model
ControlValueAccessor might be also a valid approach. It depends on the use case. CVA is useful when you want to make a component bindable with FormControl/FormGroup models which eventually brings support of angular form features like validations, etc.
its quite hard to understand at first, because im using angular first time, only for my project and i dont consider myself front-end developer. But even though i can quite understand what you are doing. Your explaining REALLY makes a difference (for example Host directive, passing ControlContainer by provider).
best advanced angular tutorials on youtube, high quality content. You cover advanced concepts in an understandable way. i am absolutly grateful for your service to the community I will definitly buy the forms course ;)
So funny, I was facing such problem yesterday, and was using 'dirty' method to solve the problem. It looks pretty awesome and I think this thing will become more popular because of your contribution :)
Thank you Dmytro, you're producing a really great and unique piece of content. Secondly, although I really like this approach in some cases, I wonder if it doesn't break the typed forms. What if I would like to have a multistep form (order) with items and addresses as separate form groups? I would like to know it upfront, validate everything etc. And with this approach the starting form group has only single field. I feel CVA would be a better choice. So my question - is there a way to use type in root component with the approach you demonstrated?
Thanks for your question:) Custom Form Control (aka ControlValueAccessor) is needed when you want to make a regular component behave as a form control and support corresponding features like validation. The pattern from the video is good for extracting a normal form control into some wrapper for reusing purpose.
@@Emekaelo Without declaring form controls in parent component you will face an error. Of cource you can make those controls optional, but it's not the best solution. If you want to make the child component strictly typed, it can be not that easy )
Sorry Dymtro but I think this solution you have provided this time, even if it works, is not the best approach to solve this kind of problems. For example, what if you want to add a different set of validators on each of the reused components? You would have to start creating new inputs on the reusable component to address this kind of things and everything would be a mess inside the component sooner or later. And what is worst, you don't need that, Angular is ready for those scenarios. I'm sure that you're aware that NG_VALUE_ACCESSOR provider and implementing the ControlValueAccesor interface should be the way to go if you want to create truly reusable form components, exactly the same way is done in the Angular forms source code. Adding controls "magically" to a parent formgroup from a control that is not declared as a formControl itself seems to me a really bad patttern and I hope no external library does it in my projects.
Hi, thank you for your comment and I respect it a lot. Firstly, I'd like to say that please don't take my solution as a "silver bullet" for each use case of "form control reusing" :) The best approach may vary depending on the requirements and goals you want to achieve. The goal of ControlValueAccessor isn't making the form control reusable (though it is also possible) but rather making a component/directive/DOM element/etc. behave as a form control that can support validation and other Angular form control features. Also, if you look at the source code of angular forms, you will see that the ValueAccessor is used to build a "bridge" between native form controls like input and the model (FormControl) that describes this input but it is not used for sharing purposes. The pattern from this video works better if you have a static and predictable group of controls that just has to be shared in some other place. Like the use case with billing and delivery address. If we assume that they are static and have the same validators I don't see any problem with encapsulating everything in one component and I don't see any reason to make the host component as the CVA. If the "magic" embarrasses you, you can drop this part of the pattern and define models explicitly from the parent component, it is also fine :) I also don't like when too much magic happens but if an adequate amount of magic can bring much cleaner code then I am fine with that. For example, when you build your form dynamically, it is very convenient when the component registers the corresponding form control by itself and you don't have to separately manage the form control models and the control component. By the way, Template-Driven forms are doing pretty much the same ;) E.g ngModel creates a FormControl instance and registers them in the parent FormGroup instance created by ngForm directive, so Template-Driven Forms are completely built with this "magic" and many developers like and successfully use them. Of course, we can have different opinions on it and I respect it. It is absolutely OK to have different points of view and I am very grateful for this interesting discussion :)
@@DecodedFrontendHi Dmytro. I found a solution to the problem of reusable forms on angular university article about custom controls. I dont know is it the best solution (learning angular about 2 months), but the solution helped me
@@DecodedFrontend I've got to agree with @gonzalocorchon6509 and I would like to point out that there are some issues with this approach: - controlKey when propagated through the codebase will become something the new developpers should learn in order to be able to work. It increases the entry cost of the codebase. - With this approach you will have not only to add validators and extra inputs to fullfill the features that reactive froms already have, but you have to introduce some error management. In your code, if the parent doesn't have a formGroup, your error will be a null injector instead of the well formatted form of angular, whilest with ControlValueAccesor you'll benefit of angular's error management. With that being said, I would like to thank you for your content, it's truely amazing, this critic is meant for us all to grow as a community and not discrediting your hard work, I understand a vidéo like this took you hours to make, and I think I can speak for everyone when I say, we truely appreciate your hardwork
Totally agree with you (see my comment above) and after a few experiments I would also add that (1) ControlValueAccessor gives a bit more flexibility when working with strongly typed form group definitions generated from API types (for example, ToFormGroupType) (2) better way of creating reusable components for arrays in case if you need a bit more code than simple *ngFor (3) ControlValueAccessor-based approach doesn't care about lifecycle hooks in contrast to Dmytro's example where you can't start adding controls in constructor directly, this means that parent component can't start pushing data before OnInit has finished. BUT ControlValueAccessor comes at a cost of way more complicated code and also has a few other issues like propagating control's validity upstream if you have validators inside ControlValueAccessor-based component.
Thanks for the lesson, it is really cool. Is it possible to use the same approach without adding a new FormGroup, but add just one control to the parent FormControl?
Another cool video, or should I say: a missing part of Angular docs! I finally understood the resolution decorators Thanks!. Given that the main form model (in this case: AppComponent) is incomplete (the remaining fields are dispersed across other components), how is this going to work with strongly typed forms? Also, if I wanted to author a form AddressGroupComponent that is usable in both ReactiveForms and template driven forms - would I have to author two separate components? I think Angular forms got a bit neglected over time.
This is so good, thanks for the video! creating a separate component that implements ControlValueAccessor and Validator stuff, just to containt an inner FormGroup and behave as a control also works the same, but this method is so much less painful. How does this work with typed form though, if a child component is registering the FormControls on the parent FormGroup directive, and it is all configured in the remplate? To me it seems the parent will not know about the existence of those controls, as far as typing goes - it will ofc work in runtime just as the video shows.
What is next and very challenging is when you have Form Array: 1. Edit mode - you have database data which needs to populate the child reactive form array. Or not if we are in Add mode. 2. Send additional data to child component. Ex: Form array object has select box which requires some database objects and also determine values of another control in that Form Array. In the end you have two @Input, the edit mode array from database and additonal values for select box, which need to communicate with parent form group. I don't know if I will find this in the course. Nevertheless, thank you! Best one yet!
This course is definitely worth it. I had some hiccups to build the component library but once it was done it works. Went through the first few tutorials and from my initial review this is a must view course for anybody working on angular professionally or seeking to work on angular professionally.
Hi! Thanks you for share this amazing feature. I 've two questions. I use this approach to create reusable input field (text/email/number and so on), select, radio etc... The reside in separate file and pass in input [controlKey], to the inputFiled component ([formControlName]="controlKey") and the magic appear. So the question is, what do you think about my solution? It's overkill? There is a simple one solution? Can I ask you what you think about compare your solution with the FormGroupDirective for create reusable form?
Thank you for your efforts and sharing knowledge, great content as always and really appreciated I'm currently working on forms enhancement and reusablility especially the form validation and custom form controls validation messages And I had a question, after this video they've become two 😂 It is about that is it possible to create a custom directive for example "controlErrorHandler" to use on form controls and it can inject the validation message component like in my case as im using angular material Is it even applicable that way or there any other better solution, any advice I'd be grateful The second question came to my mind that you've fixed my problem without even seeing a directive on the controls or inputs and im really curious. Thanks in advance.
Дмитрий, привет! Отличное видео! Помню ты был в очках, сделал коррекцию? Все тоже думаю избавиться от очков, но слышал, что после коррекции нужно не давать нагрузку на глаза, например, не сидеть долго за компьютером. P.S. не смог пройти по ссылке на курс.
Привет! Спасибо за отзыв о видео 😊 Да, я в апреле сделал коррекцию. Мне в клинике сказали, что лучше пару дней отдохнуть, а потом в обычном режиме можно работать. Там ещё многое зависит от метода. Я делал SMILE и после него на много быстрее восстановление. Я, кажется, отвечал уже в первый день на письма)) В любом случае, всё прошло хорошо, и пока полёт нормальный. Я очень рад! Какая именно ссылка не работает? Та что в описании или в комментарии? Я проверил, обе вроде работают ок. Пока можешь попробовать прямой линк - courses.decodedfrontend.io/courses/advanced-angular-forms?coupon=RUclips_DISCOUNT_2023
Hello @DecodedFrontend, your advanced concepts videos are very helpful. Can you please create a tutorial on how to build a Realtime Video chat web app in Angular 14 using webrtc protocol.
You have amazing skills both coding and teaching although I do not like the reactive way for handling forms. It seems that, when going reactive we're doing job that the framework should do for us.
@DecodedFrontend we have built a reusable set of form components, where one single input field with label and error message is represented by one component. E.g. text-input, text-area, checkbox-group and so on. So far, we passed in the reference to the form like at the begin of your video. I will definitely try your approach. Another problem with the Child Components is, that we cannot use change detection stragety onPush in the child componentes (e.g. in text-input component) because then, the form control within the child component does not seem to get notified about the parent form having been submitted and the validation state of the form control changed. Do you have an idea how that problem could be solved?
Hi Jan, In your scenario, I would consider going with the ControlValueAccessor approach because if I understand correctly, you want to make a component behave as a regular form control. I have also a separate video for that - ruclips.net/video/OrmIfW8Ak3w/видео.htmlsi=afJGk5zblGZClLvm Implementing a control value accessor for each of your input/select/textarea components will allow you to be much more flexible especially when it comes to validation. The approach in this video can work well if you have a static group of controls that just have to be reused in other forms or in some scenarios where you are generating control components dynamically.
@@DecodedFrontend I also have a question about using the OnPush strategy in a child component. When marking in the parent component to mark all controls of a dynamically added form from the child component as dirty, the re-rendering of the child component will not be called. Do you have any solutions for this case study?
We have a parent component with several child components, several of which are further nested, and it's ReactiveForm. Instead of implementing CVA for every child component, or using Inputs/Outputs, we are using FormGroupDirective. So into every child component, that is a part of the form, we inject the FormGroupDirective and add the control to the parent form. Have you seen this approach? I would like to double-check somewhere whether this approach is okay and not breaking good practices :D And what would be a better approach, FormGroupDirective or your in the video?
Hi, thank you for the video! Really good! But I have a question. How can I reset the complete Form in the Parent Component? Calling reset on the Parent Container set the forms added by the child to null?
Hey! Thanks for your question :) You reset the form the same way as for the regular one. This is because the formControl created by the child component will be eventually registered in the parent formGroup, so it means that if you reset the root formGroup then all child form controls will be reset to null (or initial values)
Thanks for video. I found an interesting thing here, So if we have some async validators, after each on destroy of our control we will fire updateValueAndValidity under the hood, and make some request. Maybe you know some workaround for this?
Hi Dmytro, How do you overcome the famous "Expression Changed After Checked" console error, in case you use in you main form template expressions like: "form.valid", since you are changing your parent component from a child(when you add the control)??
Thank you for this great idea! I use it for loose coupled components (with routing) that work together as a generic form. But i have a problem to make the injection / parentContainer optional. So if i want to use the same component as a single form component or with a parent form. Any Optional( ) or something like deps: [[Optional, NgForm]] is not working (still get an null injection error...). Any tips how to fix that?
Ah, i got it working. I used the Optional syntax wrong. First trys was with deps: [[Optional, NgForm]] Second Try was with an @Optional before the Token. But correct syntax is this: useFactory: () => inject(ControlContainer, {skipSelf: true, optional:true}) Now it works, you only have to adjust the getter for the "parent" Container to use the local formGroup instead of the one from the parent if it not exists. Also adjust the templat to provide a parentFormgroup then. Good Day folks and thx, fopr sharing tips 🙌
thanks for this video. sometimes I separate my formGroups into child components and I use output to emit child form group to parent component. do you have any idea regarding this approach?
that is a valid apporoach for simple stuff, or even use the banana in a box with ngModel. Outputs don't really mix with ReactiveForms all that well though, the idea of the FormGroup and FormControl objects is they keep all the state of the forms, and track updates, validity, dirty and touched states, and all those changes can be listened to as observables. Using an output gets you the data that you can bind to whatever function/variable you like, but it does none of the logic of FormGroups. If you wanna split a FormGroup as a child component, you can implement the ControlValueAccessor interface on the component, and make the child FormGroup look like a single FormControl to the parent form, with the data defined in the same interface. Passing validators then becomes a bit tricky, so usually let the child form worry about the validation errors, and the parent only needs to be notified of validity, touched and dirty states.
I was looking for the similar stuff and it really helped me. thanks Alot. also i am trying to write unit test cases for same standalone component and its throwing error on this saying "no provider for ControlContainer". Any idea how to fix that i created one mockClass but not working.
very nice, Thanks for sharing. But I've one question thou, how about creating a standalone component with sevral different html, how do use change this component html template dynamically?
It depends on what you want to achieve. CVA solves slightly different problems and the pattern from the video isn't a replacement for CVA but rather an alternative in some particular use cases. The goal of CVA is to make a component/directive "bindable" with FormControl/FormGroup models which will enable the angular form control functionality like validators and make it behave as a form control. The pattern from this video works better if you have a static and predictable group of controls or one control that just has to be shared in some other place or created dynamically e.g. for dynamic forms.
Yes, but there is a nuance: FormGroupDitective is referencing always the root formGroup. When you have nested form groups then you might get unexpected behavior because controls will be always registered in the root formGroup:)
Excellent explanation of this approach! However, you've now changed the design from instantiating the nested form group in the parent to instantiating it in the child then attaching to the parent where it is only accessible in the parent after ngAfterViewInit. Also, if you're going to create the nested form group instance within the child component itself like this: this.addressFormGroup = new FormGroup(...), wouldn't it be the same thing if you used [formGroup]="addressFormGroup" instead of [formGroupName]="controlKey" on the fieldset element in the child component template, since in both cases, the template will be bound to the same nested form group instance? This way, you wouldn't need to use that "rare" feature with viewProviders to make the [formGroupName] work in the template for binding to the correct nested form group instance. Or is there some extra functionality about FormGroupName directive that FormGroup directive does not have?
Advanced Angular Forms Course - Limited 10% Discount Applied 🚀
bit.ly/advanced-ng-forms-discounted
💁 Follow Me:
Twitter - twitter.com/DecodedFrontend
Instagram - instagram.com/decodedfrontend
LinkedIn - www.linkedin.com/in/dmezhenskyi
Support Channel - bit.ly/donate-to-decoded-frontend
Is there any way to buy the course from Brasil? I have only brasillians real
@@meolivares06 hi :) of course you can. You can buy it as usually and your local currency will be automatically converted during the purchase to Euro with a current exchange rate.
Hi!! Your videos are great as always, for the last 2 weeks I been trying to buy one of your courses (Advance forms), but I cant buy it, my card is being declined every time, I dont know why if already bought one of your courses before and I dont think its a problem with my bank, Im always buying stuff from internet xd
Can you help me please? I can't bind Custom Control to emitEvent: false;
I use Custom Control, but i need to "correct" some of inputs. So when user input smth - i can alter it, with setValue(value, {emitEvent:false}). It works with normal forms, but with Custom Form Control i read that updateValueAndValidity used ignoring "emitEvent" option with Custom Control.
So what to do, to make emitEvent: false work? Or what method use, to replace it?
High quality content!
Angular community is lucky having you!
Keep up the good work!
Thank you :) I happy to hear that my content helps
the best angular teacher in the whole youtube
Thank you so much! :)
Thanks!
Thank you so much for your support 🙏🏻
Дуже корисне відео, дякую, Дмитро! Дізнаюся багато нового із ваших відео, туторіали зрозумілі, актуальні, дуже подобається ваш канал!
Best Angular youtuber. Congratulations on your channel. Keep going the great work!
Glad to hear that! Thank you so much:)
Amazing video as always. I appreciate what you do and wouldn’t be where I am today without your help!
Thank you so much for your feedback 🙌
Good little dive into intervals - the ControlContainer, but honestly, it looks like you are on your way to reinvent the wheel - namely the template driven forms
Hi Dmitry, I am really glad to hear your opinion, thank you 🙌 indeed, the inspiration for self-registered form control models I found in Template-Driven forms :) I know that with TDF it would be even easier to reuse the controls since the control registration happens there automatically but sometimes we just have to stick with reactive forms.
Once again, thank you very much for this excellent video. The explanations are precise and very well illustrated. You are the boss.
Since this video came out I used this approach in two projects and I really love it.
One thing that is missing for pretty much all dynamic form videos, tutorials and courses is to be able to dynamically hide or show a control based on another ones value. If you happen to know a solid solution for that, please make a video or add it to your course. In your course you already have a section about creating a form based on a json, but no way of adding conditions for visibility. I found a working solution, but it relies on mutability.
For those wondering: I'm using a signal to hold the config of the form which includes a visibility state as well as conditions on when to show certain fields. Then I'm building a form based on that condition using the approach from this video. That way we can keep markup and from group in sync. Then I'm listening to value changes on the form group and look for any controls that might need to be updated. I then set their visibility to either true or false. However, since my config can be deeply nested I'm extracting all controls, that dependent on a another one, into a computed signal. I use this as a base to find controls to check and modify.
so thankful for this awesome content ! greetings from Egypt
I used to pass the form around to huge component hierarchies... I didn't know you could avoid it. I'll never struggle again, thanks so much!
Ok, you're awesome. Not often people make me subscribe them, keep it up!
Thanks for the great tutorial. I have been trying to do this cleanly for a long time !
Would be interesting to have some testing strategies for the subform component, as it needs to be part of a encapsulating formgroup to be functionnal.
Useful lesson!
Nice approach, thanks, will definitely use in our project!
How do you deal with the fact that nested part is invisible when inspecting a form declaration in the parent component, do you usually check the template as well?
this is a good question. I think you should look always for some balance. For example, how much I will win if apply this technique for a simple login form? Well, probably not too much, right? It will bring too much magic to your forms. But maybe if it is a complex piece of logic that would require a lot of boilerplate, validation logic, etc. Then probably a bit of magic isn't so bad 😊 Also, you can use only part of the whole pattern (providing only ControlContainer) and keep separately form models and the view if you want/need.
Interesting approach, previously in such cases I used Control value accessor. I think this has one advantage, we can keep the model reference in the main form model
ControlValueAccessor might be also a valid approach. It depends on the use case. CVA is useful when you want to make a component bindable with FormControl/FormGroup models which eventually brings support of angular form features like validations, etc.
Great video! It solved my split form issue. However, do you mind addressing the test case for this as well?
Nice video, I will investigate this solution in more detail, thank you continue as well 💪
Absolutely fantastic!!!
You've got some of the best content on Angular, thank you
its quite hard to understand at first, because im using angular first time, only for my project and i dont consider myself front-end developer. But even though i can quite understand what you are doing. Your explaining REALLY makes a difference (for example Host directive, passing ControlContainer by provider).
best advanced angular tutorials on youtube, high quality content. You cover advanced concepts in an understandable way. i am absolutly grateful for your service to the community
I will definitly buy the forms course ;)
So funny, I was facing such problem yesterday, and was using 'dirty' method to solve the problem. It looks pretty awesome and I think this thing will become more popular because of your contribution :)
Really thank you man! greatings from Argentina! have a nice day!
Хорош мужик. Є відос майже на кожну проблему з якою стикався в Ангулярі яку він ще глибоко пояснює.
Дякую, козаче 🙌🏻
. I appreciate man<
I have never ever saw teacher like you
when i had see this video i become exited to tell you realy apprecite it of you
Thank you! I am happy to hear that my work is useful 😊
Thank you Dmytro, you're producing a really great and unique piece of content.
Secondly, although I really like this approach in some cases, I wonder if it doesn't break the typed forms. What if I would like to have a multistep form (order) with items and addresses as separate form groups? I would like to know it upfront, validate everything etc. And with this approach the starting form group has only single field. I feel CVA would be a better choice.
So my question - is there a way to use type in root component with the approach you demonstrated?
NICE VIDEO, IT REALLY HELPED ME. THANK YOU!
Beautiful solution. Well explained. Well done.
You are awesome dude. Perfect solution. Thanks a lot!
Thank you. very useful content.
I have bought the advanced course :D It seems amazing!!!
Thank you 🙏🏻 I excited to hear your feedback in the future 😉
Great content. Much appreciated!
Wow, great solution. Thank you very much!!
High quality content!🔥
Great solution! Thanks a lot!
Thanks for the effort 😊
brilliant! you've earned a subscriber 👌👌
Hi Dmytro. Could you give an advice what are cases to use this approach and what are to implement custom form control?
Thanks for your question:) Custom Form Control (aka ControlValueAccessor) is needed when you want to make a regular component behave as a form control and support corresponding features like validation.
The pattern from the video is good for extracting a normal form control into some wrapper for reusing purpose.
Thank you 👍🏼
Very nice approach. Thanks a lot😃
Interesting idea. What about a template-driven forms?
Does this approach only work with reactive forms?
With template-driven forms, it should also work but for TDF you don't have to register formControl manuals because ngModel doesn't under the hood
As usual... Superb... Thanks for sharing this...
It's a nice approach, but would probably have issues with using strictly typed forms
I'm curious about what issues it'll have
@@Emekaelo Without declaring form controls in parent component you will face an error. Of cource you can make those controls optional, but it's not the best solution. If you want to make the child component strictly typed, it can be not that easy )
Thank you so much for this amazing video
You are welcome :)
Sorry Dymtro but I think this solution you have provided this time, even if it works, is not the best approach to solve this kind of problems. For example, what if you want to add a different set of validators on each of the reused components? You would have to start creating new inputs on the reusable component to address this kind of things and everything would be a mess inside the component sooner or later. And what is worst, you don't need that, Angular is ready for those scenarios. I'm sure that you're aware that NG_VALUE_ACCESSOR provider and implementing the ControlValueAccesor interface should be the way to go if you want to create truly reusable form components, exactly the same way is done in the Angular forms source code. Adding controls "magically" to a parent formgroup from a control that is not declared as a formControl itself seems to me a really bad patttern and I hope no external library does it in my projects.
Hi, thank you for your comment and I respect it a lot.
Firstly, I'd like to say that please don't take my solution as a "silver bullet" for each use case of "form control reusing" :) The best approach may vary depending on the requirements and goals you want to achieve.
The goal of ControlValueAccessor isn't making the form control reusable (though it is also possible) but rather making a component/directive/DOM element/etc. behave as a form control that can support validation and other Angular form control features. Also, if you look at the source code of angular forms, you will see that the ValueAccessor is used to build a "bridge" between native form controls like input and the model (FormControl) that describes this input but it is not used for sharing purposes.
The pattern from this video works better if you have a static and predictable group of controls that just has to be shared in some other place. Like the use case with billing and delivery address. If we assume that they are static and have the same validators I don't see any problem with encapsulating everything in one component and I don't see any reason to make the host component as the CVA.
If the "magic" embarrasses you, you can drop this part of the pattern and define models explicitly from the parent component, it is also fine :) I also don't like when too much magic happens but if an adequate amount of magic can bring much cleaner code then I am fine with that. For example, when you build your form dynamically, it is very convenient when the component registers the corresponding form control by itself and you don't have to separately manage the form control models and the control component. By the way, Template-Driven forms are doing pretty much the same ;) E.g ngModel creates a FormControl instance and registers them in the parent FormGroup instance created by ngForm directive, so Template-Driven Forms are completely built with this "magic" and many developers like and successfully use them.
Of course, we can have different opinions on it and I respect it. It is absolutely OK to have different points of view and I am very grateful for this interesting discussion :)
@@DecodedFrontendHi Dmytro. I found a solution to the problem of reusable forms on angular university article about custom controls. I dont know is it the best solution (learning angular about 2 months), but the solution helped me
@@DecodedFrontend I've got to agree with @gonzalocorchon6509 and I would like to point out that there are some issues with this approach:
- controlKey when propagated through the codebase will become something the new developpers should learn in order to be able to work. It increases the entry cost of the codebase.
- With this approach you will have not only to add validators and extra inputs to fullfill the features that reactive froms already have, but you have to introduce some error management. In your code, if the parent doesn't have a formGroup, your error will be a null injector instead of the well formatted form of angular, whilest with ControlValueAccesor you'll benefit of angular's error management.
With that being said, I would like to thank you for your content, it's truely amazing, this critic is meant for us all to grow as a community and not discrediting your hard work, I understand a vidéo like this took you hours to make, and I think I can speak for everyone when I say, we truely appreciate your hardwork
Congratulations on this civil discussion!
I came to say the exact same thing and I learned a lot.
Many thanks to both of you
Totally agree with you (see my comment above) and after a few experiments I would also add that (1) ControlValueAccessor gives a bit more flexibility when working with strongly typed form group definitions generated from API types (for example, ToFormGroupType) (2) better way of creating reusable components for arrays in case if you need a bit more code than simple *ngFor (3) ControlValueAccessor-based approach doesn't care about lifecycle hooks in contrast to Dmytro's example where you can't start adding controls in constructor directly, this means that parent component can't start pushing data before OnInit has finished.
BUT ControlValueAccessor comes at a cost of way more complicated code and also has a few other issues like propagating control's validity upstream if you have validators inside ControlValueAccessor-based component.
Thanks for the lesson, it is really cool.
Is it possible to use the same approach without adding a new FormGroup, but add just one control to the parent FormControl?
Cool! Thank you!
Another cool video, or should I say: a missing part of Angular docs! I finally understood the resolution decorators Thanks!. Given that the main form model (in this case: AppComponent) is incomplete (the remaining fields are dispersed across other components), how is this going to work with strongly typed forms? Also, if I wanted to author a form AddressGroupComponent that is usable in both ReactiveForms and template driven forms - would I have to author two separate components? I think Angular forms got a bit neglected over time.
This is so good, thanks for the video!
creating a separate component that implements ControlValueAccessor and Validator stuff, just to containt an inner FormGroup and behave as a control also works the same, but this method is so much less painful.
How does this work with typed form though, if a child component is registering the FormControls on the parent FormGroup directive, and it is all configured in the remplate? To me it seems the parent will not know about the existence of those controls, as far as typing goes - it will ofc work in runtime just as the video shows.
дуже круте відео! дякую :)
Great solution really helpful :)
Thanks you for the video.
Please make a video for creating inline-editing feature for angular material table
Fair play. Really solid explanation.
Perfect. Thank you so much, my new friend!
Excellent Video!!!!!!
What is next and very challenging is when you have Form Array:
1. Edit mode - you have database data which needs to populate the child reactive form array. Or not if we are in Add mode.
2. Send additional data to child component. Ex: Form array object has select box which requires some database objects and also determine values of another control in that Form Array.
In the end you have two @Input, the edit mode array from database and additonal values for select box, which need to communicate with parent form group.
I don't know if I will find this in the course. Nevertheless, thank you! Best one yet!
❤ Thank you. This is perfect.
another great video, Thanks
Great content, best regards from Cuba.
Such a great content! 😄
Amazing content bro great job … 🎊 🎉
Fabulous video. Does this work for a stepwise form with angular router?
dude i loved ur accent!!!!!1 thanks a lot, and keep going.
Very helpful thanks
It would be great to make a video about accessability. like how to change font-size for the whole application.
my question is by adding the formControls inside of the child component, how would you give a type to the formGroup in parent? partial?
Thanks for you question. Unfortunately, strict typing is challenging here and can be added to the disadvantages of this pattern :(
Signed up to the course
This course is definitely worth it. I had some hiccups to build the component library but once it was done it works. Went through the first few tutorials and from my initial review this is a must view course for anybody working on angular professionally or seeking to work on angular professionally.
Hi, Dimitro! Continuing the topic of reuse, would you be interested in releasing a video about route reuse strategy?
Excellent Video. I am interested on how you set values in the form form an observable stream?
Hey 👋🏻 Thanks for sharing. I just curious how does it work with typed forms? 🤔
Hi! Thanks you for share this amazing feature. I 've two questions.
I use this approach to create reusable input field (text/email/number and so on), select, radio etc... The reside in separate file and pass in input [controlKey], to the inputFiled component ([formControlName]="controlKey") and the magic appear.
So the question is, what do you think about my solution? It's overkill? There is a simple one solution?
Can I ask you what you think about compare your solution with the FormGroupDirective for create reusable form?
thanks for video 🌺
that's awesome, thank you.
Thank you for your efforts and sharing knowledge, great content as always and really appreciated
I'm currently working on forms enhancement and reusablility especially the form validation and custom form controls validation messages
And I had a question, after this video they've become two 😂
It is about that is it possible to create a custom directive for example "controlErrorHandler" to use on form controls and it can inject the validation message component like in my case as im using angular material
Is it even applicable that way or there any other better solution, any advice I'd be grateful
The second question came to my mind that you've fixed my problem without even seeing a directive on the controls or inputs and im really curious.
Thanks in advance.
Awesome!!!🚀
Дмитрий, привет! Отличное видео! Помню ты был в очках, сделал коррекцию? Все тоже думаю избавиться от очков, но слышал, что после коррекции нужно не давать нагрузку на глаза, например, не сидеть долго за компьютером.
P.S. не смог пройти по ссылке на курс.
Привет! Спасибо за отзыв о видео 😊
Да, я в апреле сделал коррекцию. Мне в клинике сказали, что лучше пару дней отдохнуть, а потом в обычном режиме можно работать. Там ещё многое зависит от метода. Я делал SMILE и после него на много быстрее восстановление. Я, кажется, отвечал уже в первый день на письма)) В любом случае, всё прошло хорошо, и пока полёт нормальный. Я очень рад!
Какая именно ссылка не работает? Та что в описании или в комментарии? Я проверил, обе вроде работают ок.
Пока можешь попробовать прямой линк - courses.decodedfrontend.io/courses/advanced-angular-forms?coupon=RUclips_DISCOUNT_2023
Hello @DecodedFrontend, your advanced concepts videos are very helpful. Can you please create a tutorial on how to build a Realtime Video chat web app in Angular 14 using webrtc protocol.
Я недавно чуть не цілий день потратив. Знайшов інше рішення, але це виглядає набагато краще)
Дякую за коментар) яке було ваше рішення, якщо не секрет?)
constructor(private rootFormGroup: FormGroupDirective) {}
ngOnInit(): void {
this.form = this.rootFormGroup.control.get(
this.formGroupName
) as FormGroup
}
Щось таке надибав😅@@DecodedFrontend
You have amazing skills both coding and teaching although I do not like the reactive way for handling forms. It seems that, when going reactive we're doing job that the framework should do for us.
@DecodedFrontend we have built a reusable set of form components, where one single input field with label and error message is represented by one component. E.g. text-input, text-area, checkbox-group and so on.
So far, we passed in the reference to the form like at the begin of your video. I will definitely try your approach. Another problem with the Child Components is, that we cannot use change detection stragety onPush in the child componentes (e.g. in text-input component) because then, the form control within the child component does not seem to get notified about the parent form having been submitted and the validation state of the form control changed.
Do you have an idea how that problem could be solved?
Hi Jan,
In your scenario, I would consider going with the ControlValueAccessor approach because if I understand correctly, you want to make a component behave as a regular form control. I have also a separate video for that - ruclips.net/video/OrmIfW8Ak3w/видео.htmlsi=afJGk5zblGZClLvm
Implementing a control value accessor for each of your input/select/textarea components will allow you to be much more flexible especially when it comes to validation.
The approach in this video can work well if you have a static group of controls that just have to be reused in other forms or in some scenarios where you are generating control components dynamically.
@@DecodedFrontend
I also have a question about using the OnPush strategy in a child component. When marking in the parent component to mark all controls of a dynamically added form from the child component as dirty, the re-rendering of the child component will not be called. Do you have any solutions for this case study?
great content, thanks from nexico
We have a parent component with several child components, several of which are further nested, and it's ReactiveForm. Instead of implementing CVA for every child component, or using Inputs/Outputs, we are using FormGroupDirective. So into every child component, that is a part of the form, we inject the FormGroupDirective and add the control to the parent form. Have you seen this approach? I would like to double-check somewhere whether this approach is okay and not breaking good practices :D And what would be a better approach, FormGroupDirective or your in the video?
Hi, thank you for the video! Really good! But I have a question. How can I reset the complete Form in the Parent Component? Calling reset on the Parent Container set the forms added by the child to null?
Hey! Thanks for your question :) You reset the form the same way as for the regular one. This is because the formControl created by the child component will be eventually registered in the parent formGroup, so it means that if you reset the root formGroup then all child form controls will be reset to null (or initial values)
Thanks for video. I found an interesting thing here, So if we have some async validators, after each on destroy of our control we will fire updateValueAndValidity under the hood, and make some request. Maybe you know some workaround for this?
Hi Dmytro, How do you overcome the famous "Expression Changed After Checked" console error, in case you use in you main form template expressions like: "form.valid", since you are changing your parent component from a child(when you add the control)??
Thank you for this great idea! I use it for loose coupled components (with routing) that work together as a generic form.
But i have a problem to make the injection / parentContainer optional. So if i want to use the same component as a single form component or with a parent form. Any Optional( ) or something like deps: [[Optional, NgForm]] is not working (still get an null injection error...).
Any tips how to fix that?
Ah, i got it working. I used the Optional syntax wrong.
First trys was with
deps: [[Optional, NgForm]]
Second Try was with an @Optional before the Token.
But correct syntax is this:
useFactory: () => inject(ControlContainer, {skipSelf: true, optional:true})
Now it works, you only have to adjust the getter for the "parent" Container to use the local formGroup instead of the one from the parent if it not exists. Also adjust the templat to provide a parentFormgroup then.
Good Day folks and thx, fopr sharing tips
🙌
thanks for this video. sometimes I separate my formGroups into child components and I use output to emit child form group to parent component. do you have any idea regarding this approach?
that is a valid apporoach for simple stuff, or even use the banana in a box with ngModel.
Outputs don't really mix with ReactiveForms all that well though, the idea of the FormGroup and FormControl objects is they keep all the state of the forms, and track updates, validity, dirty and touched states, and all those changes can be listened to as observables. Using an output gets you the data that you can bind to whatever function/variable you like, but it does none of the logic of FormGroups.
If you wanna split a FormGroup as a child component, you can implement the ControlValueAccessor interface on the component, and make the child FormGroup look like a single FormControl to the parent form, with the data defined in the same interface. Passing validators then becomes a bit tricky, so usually let the child form worry about the validation errors, and the parent only needs to be notified of validity, touched and dirty states.
Thank you for your great content. what about if this form group name is a form array ?
thanks 🌹
I was looking for the similar stuff and it really helped me. thanks Alot.
also i am trying to write unit test cases for same standalone component and its throwing error on this saying "no provider for ControlContainer". Any idea how to fix that i created one mockClass but not working.
very nice, Thanks for sharing. But I've one question thou, how about creating a standalone component with sevral different html, how do use change this component html template dynamically?
thx man, plz create a full web using angular with admin panel
Compare to implement CVA
Which is better ?
It depends on what you want to achieve. CVA solves slightly different problems and the pattern from the video isn't a replacement for CVA but rather an alternative in some particular use cases. The goal of CVA is to make a component/directive "bindable" with FormControl/FormGroup models which will enable the angular form control functionality like validators and make it behave as a form control. The pattern from this video works better if you have a static and predictable group of controls or one control that just has to be shared in some other place or created dynamically e.g. for dynamic forms.
Thank for your reply
Interesting 😊, and that could also be done with FormGroupDirective ?
Yes, but there is a nuance: FormGroupDitective is referencing always the root formGroup. When you have nested form groups then you might get unexpected behavior because controls will be always registered in the root formGroup:)
I undersrand, so it is not advisable to use FormGroupDirective for those cases, or according to your experience what is recommended. Thanks 😊🙌
Excellent explanation of this approach! However, you've now changed the design from instantiating the nested form group in the parent to instantiating it in the child then attaching to the parent where it is only accessible in the parent after ngAfterViewInit.
Also, if you're going to create the nested form group instance within the child component itself like this: this.addressFormGroup = new FormGroup(...), wouldn't it be the same thing if you used [formGroup]="addressFormGroup" instead of [formGroupName]="controlKey" on the fieldset element in the child component template, since in both cases, the template will be bound to the same nested form group instance? This way, you wouldn't need to use that "rare" feature with viewProviders to make the [formGroupName] work in the template for binding to the correct nested form group instance.
Or is there some extra functionality about FormGroupName directive that FormGroup directive does not have?
is there a git link for the code? Fantastic tutorial btw
I was wondering, how do we unit test this in jasmine?
Is there a translation option on the course platform?
My English is still very basic.
Great video