Building Forms in Angular Apps | Mosh

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] in this section we're going to look at building forums in angular so by the end of this section you'll be able to implement forms with different kinds of input fields such as text boxes checkboxes radio buttons and drop-down lists you'll be able to display validation errors next to input fields and disable the submit button if the form is not in a valid state so now let's get started all right we're gonna start this section by creating a simple bootstrap form and then we're gonna bring that to life and add some validation to it using angular so here let's open up the terminal and generate a new component so ng G C let's call this contact - form okay now let's go to contact the HTML delete all the mark-up here you want to add a form we don't need this action attribute inside this form we need to input fields one is the first name and the other is comment so once again I'm gonna use Zen coding to quickly generate marca so first we need a label next to this we want an input i want the type of this input to read text so note that you can use square brackets to put any attribute here now this input field should have a class called form - control and this is one of the classes defined in bootstrap that gives our input field a nice modern look and feel so tab this is our markup let's break it up so with this input field we can set an ID here let's call this first name and note that I'm using camel notation so the first letter of the first word is lowercase and the first letter of every word after is uppercase now if we use this ID here as the value for the for attribute of the label this improves the accessibility of our form so when the user clicks on this label this input field here will automatically get focus okay now finally we need to wrap these two elements inside a div with the class form - group this is one of the requirements by bootstrap so we want a div with a class form - group now let's move this stuff here okay now this time I'm gonna generate all this markup in one go so we want to start with a div with a class form - group now inside this div we want a label and this label shall have an attribute called for said to us a comment now next to this label we want an input with an ID attribute set to comment actually let's change this to a text area so we can have multiple lines now this text area should also have a class called form - ctrl tab okay here's our markup here's our div we have a label inside that and next to that we have a text area we don't need this name attribute so let's delete this and here's the closing div element now finally we need a bun this button should have two classes one is BTN and the other is BTN - primary and let's call this submit now one more thing is that each of these label elements need a value so the first one should be first name and the second should be comment ok now finally let's use this form on our home page first let's go to contact dot TS I want to change the selector here we don't really need this app - prefix it's extra noise added only if it's clashing with another component defined somewhere else something that you're importing from a third-party library so finally let's go to app that HTML delete all the mark up here and add our contact - form element now let's preview this so back in the browser this is our contact form so first name comment and our submit button so we have built this simple form now we want to add validation to it in angular we have a class called form control for each input field in our form we need to create an instance of the control class and with this control class we can check the current value stored in an input field we can see if the input field has been touched or untouched we can see if it's dirty which means its value is changed or pristine which means its value is not changed whether it's valid or not and if it's not what are the validation errors so for each input field in the form we need a control object now similar to the control class we have another class called form group which represents a group of controls in a form each form is essentially a control group because it contains at least one control but in a complex application you might have a form with multiple control groups for example you might have a control group for the shipping address and another for the billing address now interestingly all the properties of the control class that you saw earlier are also available in the form group class as well so we can ask a form group if it's valid or not and that returns true if all the controls in that group are valid similarly we can get all the validation errors in that group so accessing these properties of a form group is easier than iterating over all the controls in that group and checking their status so to add validation to a form we need to create a form group objects for the form and a form control object for each input field in the form this way we can keep track of the state of each input field and the entire form as a whole now there are two ways to create these control objects one way is by applying some directives in our template an angular will create these control objects for us implicitly under the hood we call forms that are built this way template driven forms so we build them using their template another approach involves explicitly creating these control objects so in our components we should write code to create new in stencils of the control group and control objects we call forms that are built this way as reactive forms previously they used to be called model driven forms now they are called reactive forms now you might ask what is the difference what is the difference between template driven forms and reactive forms the difference is that when we create these control objects explicitly we have more control over their validation logic so if you want to build a complex form with complex validation you need to use reactive forms you need to create these control objects explicitly and also another benefit of this approach is that you can unit test the validation logic of your form otherwise if you want to build a simple form with some basic validation like making some fields required or within a given range then you can use template driven forms so template driven forms are easier to create we write less code but we have also less control over the validation of our form now in this section we're going to look at template driven forms and we'll leave reactive forms in the next section so we are built its basic bootstrap form now we want to add validation to this using template driven approach so as I explained in the last lecture we template driven approach we apply a directive to our input field and angular will create a control object and associated with that input field under the hood that guess what you already know this directive that is ng model so here on this first name input field I'm gonna apply the ng model directive we use this before with the two-way binding syntax or banana in a box remember that so we used it like this here's a box here is a banana and we used engine model like this and bound this to a property or a field in our component like first thing here we don't need to a binding yet perhaps we can add this in the future but all I want to show you is that when you apply the ng model directive on an input field and its simplest form without any binding angular will create an control object and associated with this input field under the hood now let's preview this in the browser so back in chrome we get this error if ng model is used within a form tag either the name attribute must be set or the form control must be defined as standalone so basically the reason we got that error is that we didn't set a name attribute here this is a requirement because every time we apply this ng model on an input field and it needs a way to distinguish these control objects so here we set the name attribute I'm gonna use the same value as the ID so first name save now back in the browser the error is gone now I want to show you that control object under the hood so these two attributes are all you need to set in order to use the template driven approach but in this video I want to show you what is happening under the hood so I want to handle the change event of this input field and here we're gonna call the log method now I need a reference to this ng model directive I want to pass that reference to the log method so we can log in on the console for that we're gonna create a template variable so hashtag let's call that template variable first name because call it anything and as the value I'm gonna use ng model so when angular sees this it's going to set this template variable to the ng model directive that is applied on this input field okay and then we can pass this variable to our log method so here's the log method we pass first name now let's go and implement this method so back in our component I'm gonna delete the stuff that we don't need let's just keep it simple here's the log method let's give it a parameter called X and simply log it on the console this is just for Diagnostics now back in the browser I'm gonna type my name here press tab now let's take a look at the console okay here's our ng model so you can see ng model is an object with these properties now look at this property control this is the control object that I was telling you about now if you click on the value look it's an instance of the form control class in angular let's expand this here we have a bunch of properties and many of these properties come in pairs for example we have this dirty which determines if the value of the input field is changed from the moment the form was initialized in this case because I typed my name here dirty is true now the opposite property is pristine pristine means clean so dirty should be true and pristine is false okay now we have another pair in valid and valid in this case because we haven't implemented validation yet this input field is considered valid so invalid should be false and valid should be true now if you have any validation errors they're available here currently errors is null because we don't have any errors we have another pair which is touched and untouched in this case because I touch the input field or in other words I put the focus there and then moved away touched should be true and untouched should be false we have another important property value which returns the current value in the input film so what I want you to note here is that we use this form control class to track state changes and the validity of input fields when we apply the ng-model directive along with the name attribute at an input field angular automatically creates an instance of the form control class and associates it with this input field now to finish up this lecture I'm gonna apply ng model on our text area as well and set the name attribute to comment in the next lecture we're going to add some validation here all right now let's make this first name field required so in html5 we can use this required attribute on an input field and angular uses this to apply this kind of meditation on this input field so just next to this input field I want to add a div this is where will display the validation error so first name is required now to make this pretty can apply to bootstrap classes one is alert and the other is alert - danger which puts this in a red box now we don't want to display this at all times you want to display this only if the input field is not valid so we use the end if directive that you have seen before now how do we know if the field is valid or not well back here in the console you saw this ng-model directive right and we looked at this control property this control has a property called valid from here we can tell if an input field is valid or not but there is a simpler way so let's collapse this property if you look at the properties of this ngmodel directive we have all those properties you saw earlier as part of this class as well so here we have valid which is a computed property so when we use this property internally the ngmodel directive delegates to the underlying form control object so here has the value of the ng-if directive we can reference our directive so earlier we created this template variable first name we can type first name dot valid now we apply the not operator here so we'll render this Dib only if the first name is not valid let's test the result so back in the browser okay you can see the error is initially displayed here which is a little bit too confronting for the user because they haven't done anything wrong yet so I will show you how to fix this problem in a second let's type something here look as soon as I type one character the error is gone and when I delete this the error is back so the validation is working now let me show you how to show this error only if the user puts focus in this input Ville and moves away without entering a value so back here I'm gonna change this condition I'm gonna add first name that touched and first name not valid with this I'm telling angular to render this div if this input field has been touched which means it received focus but the user left this input field without entering a valid value so let's try it again back in the browser so look initially the error is not here now I'll put the focus if I press tab I get this error so this is how we add the validation errors next to each input field we add a div with the validation error and render it only if that input field has been touched and it's not valid in the next lecture I'm going to show you different kinds of validation errors so in the last lecture you saw the required validation error in angular we have a few built-in validators that are based on html5 validation attributes so let's say we want to set a minimum links for our first name you can set that here it has to be minimum three characters we can also set a maximum links let's say 10 characters now finally we can also apply a pattern now in case of a first name it doesn't quite make sense but if you have something that you want to apply regular expression validation on you can use this pattern attribute so I'm gonna set this to banana and this means only the word banana is a valid value in this input field now when you have multiple validation attributes you cannot show them all with one div like here we want specific validation errors okay so we want to make a small change here first I'm gonna remove this validation error here now inside this div you want to have a separate div for each validation error so div first name is required now we want to render this only if we have the required validation error so here as the value for the ng-if directive we type first name remember here we have a property called errors now from here we can check to see if we have this error required so in this error object we have one or more key value pairs and the keys are the validation errors I'm going to show you the content of this errors object in a second now let us add the second div so another div first name should be minimum three characters okay now once again we want to render this only a first name that errors that min length is true yeah I'm gonna duplicate this and for the last one I'm gonna use pattern so first name doesn't match the pattern okay now let's inspect this in the browser so initially no error I put the focus here move away we get this error message first name is required I type only one character now look we have two errors first name should be minimum three characters and the second error is about a regular expression so if I type two more characters the first error is gone but the value we have here doesn't match the pattern so let me change this to banana and all the errors are gone so this is how we add multiple validation constraints on an input field we simply use these standard html5 attributes required min length max length and pattern and for each error will have a separate div now finally before we finish this lecture let me show you the content of this errors object so once again here I'm going to type one two now let's open up the console so here's our ng model we have this error object look we have two key value pairs keys are min lengths and pattern look at the values so this object has two properties actual length which is two and the required lengths which is three we can take advantage of these properties and render a dynamic message to the user so here for the min length validation error instead of hard-coding this value 3 here we can render it dynamically because tomorrow we may decide to change the value of the min length attribute we don't want to change this in two places okay so here we add interpolation and render first name that errors that min length dot now the property we want to add here is required length so dot require head length let's test this so back here I type my two characters tab and first name should be minimum three characters which is rendered dynamically back to our forum I want type an invalid value here now as a best practice we should highlight the invalid input fields this improves the usability of our form so how do we apply a red border to this input field well let's inspect this all right here's our input field now there are so many attributes here don't worry about them just look at this part class so we have the form - control class that we applied in our template but we also have three more classes that are added by angular dynamically one is ng - invalid the other is ng - dirty and ng - touched we can use these classes to apply styles to invalid input fields so let's go to styles that CSS here I'm gonna add a new rule so if you have an element with the class form that's control which should be applied on all input fields and also in the same element we have ng - touched as well as ng - invalid I wanna make the border of that element - pixel solid red straight back in the browser so I put the focus here and tab and here we have a red border as you build forms with angular you will notice that your templates get more complex now in this video I have increased the font size and for that reason you don't see all the markup here so we have to scroll to the right however on your screen chances are you have everything in one view but what I want to point out here is that as a best practice your code should be formatted in such a way that another developer does not have to scroll to the right and to the left to see what's happening so let me show you a cleaner way to write this template we can break up these lines and list one attribute on each line for example consider this input field we can add all these attributes like this one on each line I note that I'm listing all the validation attributes first so another person another developer reading this code they know immediately what are the validation constraints of this input field after these I add ng model and immediately follow that I add the name attribute as well as first name set to ng model now we don't really need this event binding here this is purely for this demo and finally we add ID type and class then similarly we can format our validation errors like this so we have the parent div I add all the classes here and then ng if so here you can easily see this ng-if without having to scroll to the left and right now for each validation error we can break it up like this so I put the error on the next line and this is much easier to the eyes like this so this is the end result which is way cleaner than what we had before hi thank you for watching my angular tutorial if you enjoyed this video please like it and share it with others also you can subscribe to my channel for free new videos every week this video is part of my complete angular course with almost 30 hours of high quality content where you learn everything about angular from the basic to the advanced topics all in one course so you don't have to jump from one tutorial to another in case you're interested we can get this course with a big discount using the link in the video description and if not that's perfectly fine continue watching as the next section is coming up
Info
Channel: Programming with Mosh
Views: 323,070
Rating: 4.9155164 out of 5
Keywords: angular, angular.js, angularjs, angular 2, angular2, angular 4, angular4, mosh hamedani, javascript, jquery, form, programming with mosh, code with mosh
Id: hAaoPOx_oIw
Channel Id: undefined
Length: 25min 3sec (1503 seconds)
Published: Wed Sep 06 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.