Suggested Videos
Part 12 - Customise ngx-bootstrap datepicker | Text | Slides
Part 13 - Angular ngif directive | Text | Slides
Part 14 - Angular disable browser validation | Text | Slides
In this video and in the next few videos we will discuss Form Validation in Angular with examples. Along the way we will discuss validating textboxes, check boxes, radio buttons, dropdownlists etc. We will also discuss, how to fix one of the common error that we get when exporting NgModel into a local variable. The error that we get is, cannot assign to a reference or variable. We will discuss what causes this error and how to fix it.
To understand validation in Angular, we need to understand the following 3 sets of properties in Angular.
These 6 properties are available at each individual form control level and also at the form level. Let's look at these properties in action at an individual form control level. Consider the following "Full Name" field on our CreateEmployee page.
Please note :
At this point, view the page in the browser and notice the following
We can use this template reference variable employeeForm to access the validation properties at the form level. Copy and paste the following HTML in create-employee.component.html
Also, make the Email input field required by placing the required attribute
Save the changes and view the page in the browser.
On our form, we do not want to display the validation properties and their values. So to keep out form clean, please remove the HTML from the form, that displays the validation properties and their values.
Part 12 - Customise ngx-bootstrap datepicker | Text | Slides
Part 13 - Angular ngif directive | Text | Slides
Part 14 - Angular disable browser validation | Text | Slides
In this video and in the next few videos we will discuss Form Validation in Angular with examples. Along the way we will discuss validating textboxes, check boxes, radio buttons, dropdownlists etc. We will also discuss, how to fix one of the common error that we get when exporting NgModel into a local variable. The error that we get is, cannot assign to a reference or variable. We will discuss what causes this error and how to fix it.
To understand validation in Angular, we need to understand the following 3 sets of properties in Angular.
touched
untouched
|
pristine
dirty
|
valid
invalid
|
These 6 properties are available at each individual form control level and also at the form level. Let's look at these properties in action at an individual form control level. Consider the following "Full Name" field on our CreateEmployee page.
<input id="fullName" required type="text" class="form-control" name="fullName"
[(ngModel)]="fullName" #fullName="ngModel">
Please note :
- We have made the Full Name input field required by including required attribute on the input field. required is HTML 5 attribute. This attribute specifies that a field is required. Besides required, there are other HTML 5 validation attributes like maxlength, pattern, min, max etc. The following page has the HTML 5 validation attributes list.https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation
- We will discuss most of these attributes with examples, in our upcoming videos. Angular uses these HTML 5 validation attributes, for validating form fields and displaying meaningful error messages to the end user.
- We are exporting NgModel into a local variable called fullName. To do this we are using #fullName="ngModel". This variable fullName is called with different names - local variable, template variable and template reference variable.
- At this point if you view the page in the browse you will see the following errorCannot assign to a reference or variable!
- We get this error because, Angular generated form model creates a property with name "fullName" and we are also creating a local reference variable with the same name by exporting ngModel to #fullName. Hence we get the error - Cannot assign to a reference or variable.
- One way to fix this error is, by giving our local template reference variable a different name other than fullName. So if we change #fullName="ngModel" to #fullNameControl="noModel" the error goes away.
- The other way to fix this error is by using our own model instead of using the Angular auto generated form model. Notice we have our own employee model in employee.model.ts file in models folder. We will discuss using our own employee model in our upcoming videos. For now let's continue discussing the validation properties provided by Angular.
Include the following HTML table, just after the Full Name field in create-employee.component.html. Notice we are using the local template variable fullNameControl to access the 6 validation properties provided by Angular
<table border=1 style="border-collapse:collapse; font-family:Arial;
table-layout: fixed">
<tr style="background-color:rgb(170, 120, 12); font-weight: bold">
<td colspan="3" style="padding:3px; white-space:nowrap;
width:100%">
<h4>Full Name Field</h4>
</td>
</tr>
<tr style="background-color:rgb(212, 149, 13); font-weight: bold">
<td style="padding:10px; white-space:nowrap; width:33%">
<div>touched : {{ fullNameControl.touched }}</div>
<div>untouched : {{
fullNameControl.untouched }}</div>
</td>
<td style="padding:10px; white-space:nowrap; width:33%">
<div>pristine : {{ fullNameControl.pristine
}}</div>
<div>dirty : {{ fullNameControl.dirty }}</div>
</td>
<td style="padding:10px; white-space:nowrap; width:33%">
<div>valid : {{ fullNameControl.valid }}</div>
<div>invalid : {{ fullNameControl.invalid }}</div>
</td>
</tr>
</table>
At this point, view the page in the browser and notice the following
- touched is false and untouched is true as we did not touch the Full Name field yet. Notice when we click in the Full Name field, touched is still false and untouched is still true. These 2 properties change when the field loses focus. So when we tab out of the control, notice both the properties change as expected.
- Notice the pristine and dirty properties. pristine means the form control value has not been changed and dirty means the value has been changed. Notice when we type something in the Full Name field the properties change as expected. Even after we delete everything we typed, the dirty property remains true because we have changed the value in the form control.
- Finally notice valid and invalid properties. Since we have required attribute on the Full Name field, valid is false, if we do not have anything typed in the field. The moment we type something, valid is true and invalid is false. If we delete everything we have typed, valid becomes false and invalid becomes true as expected.
We also have these same 6 properties at the form level. Notice the form tag, we are already exporting ngForm to a local template variable - employeeForm.
<form #employeeForm="ngForm" (ngSubmit)="saveEmployee(employeeForm)">
We can use this template reference variable employeeForm to access the validation properties at the form level. Copy and paste the following HTML in create-employee.component.html
<table border=1 style="border-collapse:collapse; font-family:Arial;
table-layout: fixed">
<tr style="background-color:silver; font-weight: bold">
<td colspan="3" style="padding:3px; white-space:nowrap;
width:100%">
<h4>Employee Form</h4>
</td>
</tr>
<tr style="background-color:silver; font-weight: bold">
<td style="padding:10px; white-space:nowrap; width:33%">
<div>touched : {{ employeeForm.touched }}</div>
<div>untouched : {{ employeeForm.untouched
}}</div>
</td>
<td style="padding:10px; white-space:nowrap; width:33%">
<div>pristine : {{ employeeForm.pristine }}</div>
<div>dirty : {{ employeeForm.dirty }}</div>
</td>
<td style="padding:10px; white-space:nowrap; width:33%">
<div>valid : {{ employeeForm.valid }}</div>
<div>invalid : {{ employeeForm.invalid }}</div>
</td>
</tr>
</table>
Also, make the Email input field required by placing the required attribute
<input id="email" required type="text" class="form-control"
name="email" [(ngModel)]="email">
Save the changes and view the page in the browser.
- Notice when we type "Venkat" in the Full Name input field,
- touched property both at the input field level and form level is set to true
- untouched property both at the input field level and form level is set to false
- Same is true for dirty and pristine properties
- However, notice valid property of the Full Name field is true but the form valid property is false. This is because, Emal field is also required and we did not enter anything in the email field, so email field is invalid and as a result the form is invalid.
- The moment we type something in the email field, the form valid property turns true.
- So this brings us to an important conclusion - If all the form fields are valid, then the form is valid. If any of the form field is invalid the form is also invalid.
- Along the same lines, if any of the form field is touched, the form is also marked touched and if any of the form field is dirty the form is also marked dirty.
- Include the HTML 5 validation attributes such as required for example on the input field you want to validate.
- Export ngModel directive to local template variable
- Finally use the template reference variable to access the validation properties like touched, dirty, valid etc.
Along the same lines, to check if the form is valid
- Export ngForm directive to a local template reference variable
- Then use the template reference variable to access the validation properties at the form level.
On our form, we do not want to display the validation properties and their values. So to keep out form clean, please remove the HTML from the form, that displays the validation properties and their values.
Nice article and easy to understand. Really help to get into a new language. Just one typo there #fullNameControl="noModel", should be ngModel. We appreciate your tutorials.
ReplyDeleteThere is one typo error in the line #fullNameControl="noModel" instead of noModel it should be "ngModel". May this help someone.
ReplyDeleteThanks
Please update spelling in --> to #fullNameControl="noModel"
ReplyDeleteto be ngModel
Hi Venkat,
ReplyDelete"Angular generated form model creates a property with name "fullName" and we are also creating a local reference variable with the same name by exporting ngModel to #fullName."
My question here is: Instead i create a 'local reference variable' explicitly, can i use the name that angular which already created?