Angular 12 - Building Custom Controls using Control Value Accessors

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone in this video i'm going to show you how to build your very own reactive form controls in angular 12 using control value accesses [Music] okay so before we get started i just want to quickly mention that i will not be discussing the basics of reactive forms in this video so if you have no experience whatsoever building a reactive form i suggest you go find another video learn how to do the basics and then maybe come back to this video with that said i'm now going to show you what we're going to be doing right now so basically what i've got is just a simple little form here with some settings on it you can see it's basically capturing two check boxes so there's a checkbox for sms notifications and there is a checkbox for email notifications the values that are assigned here are assigned to boolean values at the moment so for this one we can see it's checked so it's showing yes down here and then for the email one it's unchecked so it's setting to no so this is the default uh situation that we have now if i change the values of both of these and then click submit well we can see now the values have been reflected down here pretty standard this is a very simple reactive form okay what i'm also going to show you here is the fact that we can disable controls and we can re-enable them just like that okay now as you can tell this is not very interesting and it's quite possible that a requirements come in to improve this experience and somebody said okay let's make this a slider control instead well slider controls by default are not supported in angular as form controls so that's what we're going to be focusing on in this video but let's have a look at the code that we have right now based on the current form that we have so i've got the code in front of me with my project open and by the way for anyone who's asking yes i do have a copy of this code it's on my github account i'll leave the information to getting this code in the description now if i expand the source folder and i come into app and i have a folder called pages then settings i have basically a component here that represents that page so we'll open up the settings component ts and the html file so first i'll check out the ts which is our component cobine and we can see we've got a form group here that i've got defined as a variable and in the constructor i'm instantiating that to basically be the result of a form builder group call all right so we've got two controls that we're defining for this group one is the allow sms and another one is allow email now the values are set based on a settings uh field that we've got here which as we can see it's just got two flags sms set the true and email set to false which is why we have the sms checkbox checked by default and the email one unchecked so that's pretty much all we need to know in here for the moment if we go and check the template file what we've got is basically a very simple form here with a form group applied to it it says pre-standard for reactive forms and then we have an input of type checkbox that maps to each control so there's allow sms and allow email now we're linking it based on the attribute from control name right so that's currently what we've got now commented underneath each input control is actually a custom control which i've created called a slide toggle so i'm going to uncheck those and i'm going to comment out or not sorry uncheck uncomment and i'm going to comment out these ones and then i'm going to save it and i'm gonna go back to see what we've got so as you can see the check boxes are gone and we have this slider component now obviously they're both just saying yes so what that means is is that we're not honoring the form controls at the moment for this component it's just basically a user control that we can just toggle backwards and forwards and that's it right for either one so if i say yes and then no or no and then yes in this case and go submit you can see no values down here will change right and that's because these are not wired up to be form controls so the first step you might take is to actually add the form control name to the input and then you would hope that that would work all right but before we try that let's have a look at how this component actually works so we'll jump back in the code and just take a quick look so we're back in the code and i'm going to keep this template file open but we don't really need this one to remain open so i'm going to close that and now what i'm going to do is i'm going to come down to where this slide toggle component is located so in this code base it's located under shared controls and then slide toggle i'm going to open up the ts file and the html and i could open the css but i don't think we're really going to worry too much about that right now so we'll come to the ts file first and this is pretty straightforward the key factor here is that this is checked flag is toggled on and off right so basically this is the thing that we want to control in our form controls now at the moment it's just declared as a local variable to this component and we have a toggle method which basically is triggered when we click on a div alright in our component it then will basically toggle the state on and off as long as it's not disabled right which by default is always well in this case it's always set to false but we will fix this up a little bit later all right so it's pretty straightforward that's that's all it really is so it's just a root div with some spans that kind of updates the text based on whether it's checked or not and then it obviously does it moves a little button around based on whether it's checked or not and that's all made by classes and some custom animation inside of our css file all right so it's a little bit of css trickery there not much to explain all right all you really need to focus on here is the fact that this is checked needs to be controlled by our form control well and so is is disabled actually to be honest uh but we'll look at disabled a little bit later so how do we now that we understand what we're working with convert this component to be accessible as a form control well that's where i mentioned early on that we need to implement something called a control value accessor now there's two parts to it there's one where you need to register this component with the reactive framework or the reactive part of angular and essentially how that works is that we need to register this component as an accessor using the ng value accessor provider now how that looks is essentially like this so first thing i'm going to do and i'm just going to do some copy and pasting here i'm going to paste at the top here basically the control value accessor interface and a constant that represents the injection token that you need to register this control or this component as a form control okay now i won't get into how injection works in angular that's a topic for a completely different video but in order for this to work we need to actually do some registration and it looks a little bit like this so if i go comma and paste in this code well i need to update this reference here so let me just quickly do that and i need to add that to the angular core there so what does this code actually do well essentially in short it registers this component as a potential provider for a form control okay and it does this by using that entity value access as a key so when reactive forms or reform group looks down your template now if it finds this component and it finds it with a say form control or form control name attached to it it's going to then look for special methods on your component okay and that's kind of initiated by this use existing forward ref which is saying whatever this current provider is the special method you're looking for is going to be referred to to this component which is basically this one here right so at this point we're saying the control value access of logic that's needed for this component will actually be in this component right and volte is needed because you can have multiple ng value accesses so any ngo value access that you ever write is always going to have multi set to true that's just something you do in angular okay so i'm going to actually move this over and save and now the second step to this is to actually implement the control value exit interface that we have up here so i'm going to come down and go implements and then i'm going to put control value access up now obviously you're going to get an arrow here because i haven't implemented the functions so i'm just going to use the inbuilt intellisense there to help me and now what that does is it produces three functions now i'm just going to cut these out for a second and move them underneath my variables just before the toggle and i'll space them out a bit so i like my spacing and basically these are the three functions that are required for a control value accessor to do its thing in the angular framework now what do these three functions do well the first one is right value and what this is essentially used for is for you to wire up your component to accept an incoming value from a form control so if we go back to the ts file i know i said i wasn't going to need it but i do need it if i come back to the settings file when we're writing this value into this control and this is this in this case it's during construction but it could be if we go this dot form group dot get allow sms dot set value right we could even do this and say false right if we do this we're writing a value down into the control that's utilizing this right so in the case of our slide toggle it's going to call this function right so we usually would do something like this we'll go okay well i need to update that is checked flat because that's the thing that's indicating the state of our component so we can go this dot is checked is equal to object now i'm going to be honest with you i don't like the fact that it's called object so i'm going to change it to checked and i'm going to change the type to boolean right that's just so it looks more correct to me but essentially if we do that right and i'm going to take this code out if we do this and we save and then we come over to our settings page component and oh before we do that let's comment out these exceptions the moment if we do all that we come to our settings page and now what we do is we register this as the form controls so let's say we do that and then for the other one we grab this one and we assign that here like so if we save this and now we go and check the application and look at that so now we've got the ability to write to our control so if we remember by default we had the sms notifications configured to be on but we had the emails already configured to be off right so now you can see it's actually switched to an unchecked state or in this case we say no right but the one thing we haven't handled well there's a couple things we haven't handled here one is if we change it like so and click submit well nothing happens right these values don't get updated right so it's not propagating we also can't disable it right or enable it at the moment this is also ineffective so let's deal with the first one which is if we change the value and click submit how do we go about getting this to work let's jump back in the code and i'll show you how this is done so i'm back in the code and i'm going to come over to my slow toggle component the one which we implemented the control value accessor and now we're going to look at this second method which is register on change now what this actually takes is a function believe it or not even though it says any this is actually a function that you have to explicitly call when you yourself in this component have changed the value so in our component it's when we change the value of checked or is checked i should say that's when we need to call this function to let the form control that's registered against this component update its value accordingly right so it looks a little something like this so the first thing we need to do is we need to register on change here in our component so i'm just going to put any for the moment but i'll change the type in a second and then all i need to do in here is go this dot on change is equal to fn which i will change this at least to unchange like so and assign it appropriately also get rid of the comment now this is just the first step right we need to also call this at some point right where we need to call it is when we change the ch is checked value which is down here okay so just after this has been assigned i'm now going to call this dot on change passing in this dot is checked all right now because this is a boolean flag and i'm comfortable that this is always going to be a boolean flag i'm going to actually change this function here to be an arrow function so i'm going to set this with a value or we can say yeah is checked and that's i'm sorry that's going to be boolean and that's going to return a void right so this is the signature we're going to use for our onchange and i'm going to assign it there as well okay now with this change alone or these changes alone this should now propagate whenever we check on the slider toggle the value of is checked up to the form control and when we press submit we should now see the reflected changes well let's check that out so we're back on the screen and now what we'll do is we'll toggle each one to the opposite directions and now sms down here should be no and email should be yes when i click submit and there you go look it actually changed so now we have the ability of changing these whenever we like right so we can turn them on submit turn them off submit and so on so forth right now what we still can't do is we can't disable the controls so if i click disable you can see that they're both still able to be changed which is not really that good right we still want to be able to have the ability to disable controls and enable them and things like that so now let's have a quick look on how we can do that so we're back in our slide toggle component and now we want to know how we can implement a disabled right so we've got this flag here already but it's always set to false right we want to control this from our form control from the outside so how do we do that well if we looked at when we implemented control value accessor we only actually got three methods we've seen right value we know what that does we're seeing register on change we now know what that does and then there's this register untouched now this isn't actually used for disabling the control this is for something else and i'll come back to it in a minute but when we implement control value accessor we have to implement all three of these okay regardless of whether we use them or not but this interface also has a fourth function if we scroll all the way down so register on change register untouched and now there's this one called set disabled state right this one is actually optional you don't need to implement this but you know for the purpose of this example we're going to all right so what i'm going to add under register unchanged is a function that i'm just going to copy and paste in that looks like what we need it to be right so there's our set disabled state there's our boolean flag so this is actually really really simple right all we really need to do is just go this dot disabled equals is disabled right and if we save this and we go back to the form and now if i come over here and i click on the disable button well look at that the styles have now changed on the buttons right they're actually applying a style that i've set inside the code which sets a class of disabled you also can see that if i try to click on them they won't actually do anything right because it's setting that disabled flag if i click enable again now we can change them and we can submit and everything is how we expect it to be all right so that's really really cool now the last thing that we'll talk about before we end this video is the registered untouched so before we go back to the code let's have a look at form controls in general so if i hover over our component now and we look at the dom for this what you're going to see on our actual element is a whole bunch of attributes right but what's most important is the classes so as you can see at the moment the class here says ng untouched and ng dirty right now when we change the value of a control it will actually set this energy dirty flag and we can see that by when we refresh and we target this for the first time and we find the actual attribute now you can see it says ng pristine what this means is basically the control hasn't been interrogated in any way yet but as soon as we click on it now we can see that it is in fact dirty so this tells the form control hey look you've edited something and currently it's valid because we don't have any reason to make it invalid but basically you know this is the behavior that we have all right for ngd but you'll see it still says untouched now technically this is not true we did just change this right so we need to flag this in our component to say that once we've clicked on it that it has in fact been touched so that's what we're going to do right now so we're back on our component and now what we're going to do is we're going to ensure that we tell our form control that on the first time that our toggle is clicked that we have actually touched it okay so what that's going to involve is us adding a boolean flag here the same is touched or something to that nature and we're going to set this to false by default and then we're going to come down to our register untouched we're actually going to create another function so here we are going to have on touch all right we'll set it to any for the moment and then we're going to use that to register on touch right so on touch equals fn again i'm going to change this to on touch like so just for better names right and essentially all we really need to do here is mark whether this actually happened or not so we only need to call this once so this is really just a void function like so so i'm going to do the same up here i'm going to update this to an on void function and i also have to specify that with an exclamation there because it's angular 12 and now that we've registered that function we need to call it at the appropriate moment so is touch by default is false so if we come down to our toggle and we've got to say we're not disabled right we now need to after probably this code here indicate if this is a touch right so if this dot is was it first touch did i call it is touch if it's not touch sorry then so basically if not touch therefore we've never touched this before we're going to set it to true all right so this is true and then we're going to set on touch we're going to call untouch so this will tell the form control or the yeah the control in the form group hey look it's been touched and this boolean flag will prevent it from fight continuously firing this because touch should only really happen the first time you touch this control so now if we save this and we go back and take a look at what we have in our web page so now i'm looking at my component i can see it's untouched and it's also pristine if i click on it now you can see the ng-touched class has been applied and not the ng untouched all right if i subsequently click it you can see that it stays energy touched it also stays empty valid and ng-dirty because well at this point it is dirty it's a dirty field right but it's also valid because there is no invalid state here cool so that's pretty much it that's how you can build your own custom control using control value accesses thanks for watching don't forget to like the video subscribe to my channel and hit that notification bell and i'll see you all next time
Info
Channel: Lyrad Digital
Views: 365
Rating: undefined out of 5
Keywords: angular, angular12, angular 12, control value accessors, controlvalueaccessor, formcontrolname, form controls, custom controls, angular 12 tutorial, reactive forms
Id: pRF97kss8eI
Channel Id: undefined
Length: 23min 55sec (1435 seconds)
Published: Fri Sep 24 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.