Details about Angular2 form-Template-Driven Forms ),
In web development, form estimation is the most commonly used one, and it is also the most troublesome and prone to problems. In a slightly more complex application, in addition to using form elements to collect data, we also need to verify that several pieces of data may be associated with each other, then, different business logic is called based on different data values.
Using the data binding function provided by Angular, we can easily obtain user input data in the component. Angular also provides several verification methods to facilitate data verification. However, some custom data verification, data interaction, and business logic still need to be processed by yourself.
Angular2 provides two form implementation methods: 'template-driven' and 'model-driven ). In this article, let's take a look at the template-driven form. As the name suggests, most of the form-driven forms are in the template. You can add attributes such as ngForm, ngModel, and ngModelGroup to the template to define the template and verification information, and its data interaction with components.
Instance
Is the instance interface used in this article:
It is a form of user information input, including four fields: user name, phone number, city, and street. It demonstrates how to use the form, add verification to each field, and display the verification result, and how to identify errors in components and obtain error information.
The project source code can be obtained from github. This project contains several Angular2 form-related instances. You can use the following command to obtain the code corresponding to this article:
git clone https://github.com/Mavlarn/angular2-forms-tutorial
Go to the project directory, run the following command to install the dependency, and then run the test Server:
Cd angular2-forms-tutorialgit checkout template-driven # Check the tagnpm installnpm start used in this article
The project is based on the previous Angular2-basic template, and the Code related to this tutorial is in the 'template-forms' directory.
Introduce FormsModule
First, we need to introduce the FormsModule in app. module. ts.
Import {FormsModule} from '@ angular/forms'; // omit other @ NgModule ({imports: [BrowserModule, FormsModule], // omit other })
Initial form
Then, we start with a basic html form:
<Form> <label> name: </label> <input type = "text"> <label> Tel: </label> <input type = "text"> <label> City: </label> <input type = "text"> <label> Street: </label> <input type = "text"> <button type = "submit"> Save </button> </form>
In the actual example, the bootstrap form style is used, and a set of input boxes should look like the following. However, in this article, to save the page display space, I omit the div, form-group, etc. We only need to care about how to use a template-driven form in Angular2. If you want to view the complete code with styles, view the source file.
<Div class = "form-group"> <label class = "col-sm-2 control-label"> Name: </label> <div class = "col-sm-10"> <input class = "form-control" type = "text"> </div>
NgForm
In the above form, we didn't use any functions of Angular2, such as data binding, or other commands. However, Angular2 implements an instruction 'ngform' on <form>. In this way, all html form forms will be initialized using the ngForm component.
Use ngForm object
Next, we need to access the ngForm instance in the template, so that we can get data from this instance or get the data verification status.
Angular2 provides a template to reference variables. With this function, we can reference template reference variables in the same element, sibling element, or any child element. It is hard to understand. Let's look at an example:
<input #phone placeholder="phone number"><button (click)="callPhone(phone.value)">Call</button>
In this example, we use#phone
Defines a variable, which refers to the input element,phone.value
That is, the value entered in this input box.
Besides#,
You can also useref-,
For exampleref-phone
Format definition and#phone
Is the same.
We can use this method to obtain the current reference for any DOM element or any Angular2 command. In the example of this form, we can obtain the reference of this ngFrom:
<form #userForm="ngForm">
Here, 'ngform' is the current instruction, so that we can useuserForm
Obtain all data in the form.
Submit Form
In html, We need to submit a form, which will write an action attribute in the form, and then submit it with a button of the type 'submit. However, in Angular2, we need to use the ngSubmit event:
<Form # userForm = "ngForm" (ngSubmit) = "logForm (userForm)"> <button type = "submit"> Save </button> </form>
In this way, when you click the Save button, Angular2 uses its own authentication mechanism to verify all the data, and then calls the 'logform (userForm) 'method.
In our components, implement this method:
logForm(theForm: NgForm) { console.log(theForm.value); if (theForm.invalid) { // handle error. }}
In this method, we can use theForm. invalid to obtain the status of whether the form is successfully verified, or use 'theform. value' to obtain all the form data. Here, we print the form data to the console to check the data. How to obtain control data and status from this form reference will be discussed later.
Use ngModel to bind data
Next, we need to bind data. Assume that our business is to obtain user data when opening this page, and then display it on the page form. We create a simulated user data in the component constructor:
Export class TemplateFormsComponent {user: any; constructor () {this. user = {name: 'zhang3', mobile: 13800138001, city: 'beijing', street: 'chaoyang Wangjing... '};}}
Then, bind the data in this component to the template page in the template:
<Input type = "text" name = "name" [(ngModel)] = "user. name "> <input type =" text "name =" mobile "[ngModel] =" user. mobile "> <input type =" text "name =" city "[ngModel] =" user. city "> <input type =" text "name =" street "[ngModel] =" user. street "> <! -- Other input boxes are similar -->
Here, we use[(ngModel)]="user.name",
This is a two-way binding method. In this way, when we modify the data on the page, the updated data can also be obtained in the component. If the data is updated in the component, it can also be updated on the page.
To demonstrate the difference between two-way binding and documentary binding, we only use two-way binding for names and one-way binding for others, that is[ngModel]="user.mobile"
. One-way binding using [] is the binding from the template to the component, that is, the input data in the page changes, and the data in the component also changes. However, the data update in the component does not cause the data update on the page.
One-way binding can reduce data update checks and improve performance.
If you do not need data initialization, you can only use ngModel. For example:
<input type="text" name="city" ngModel>
In this way, the user data we create in the component cannot be displayed on the page, but he can still bind the data entered on the page to the data in the component.
In Angular2, create a form control FormControls using ngModel and the name attribute. For example, the preceding <input name = "city" ngModel> corresponds to the city control in a userForm. Since we upload this userForm as a parameter to the method in the submission method, we can obtain all Form Controls in the method theForm. controls is a Map-type object. The key is the name of all form elements, and the value is a FormControl object, which stores data, verification results, and whether to modify the status. It is precisely because of these FormControls that we can use theForm. value to obtain the data in the form. When we click the Save button, we can see the form data in the log:
{Name: "James", mobile: 13800138001, city: "Beijing", street: "Chaoyang Wangjing ..."}
Display by ngModelGroup
In general, our model data may be nested. For example, for user information, cities and streets may be in an address object address, for example:
{Name: "James", mobile: 13800138001, address: {city: "Beijing", street: "Chaoyang Wangjing ..."}}
You can use ngModelGroup to group such data. The template is like this:
<Form # userForm = "ngForm" (ngSubmit) = "logForm (userForm)"> <label> Name: </label> <input type = "text" name = "name" [(ngModel)] = "user. name "> <label> Phone: </label> <input type =" text "name =" mobile "[ngModel] =" user. mobile "> <fieldset ngModelGroup =" address "> <label> city: </label> <input type =" text "name =" city "[ngModel] =" user. address. city "> <label> street: </label> <input type =" text "name =" street "[ngModel] =" user. address. street "> <button type =" submit "> Save </button> </fieldset> </form>
In this way, we encapsulate the address information in an address object. Note that the structure of the data we bind has also changed. In this way, we also need to modify the user data in our components:
Export class TemplateFormsComponent {user: any; constructor () {this. user = {name: 'zhang san', mobile: 13800138001, address: {city: 'beijing', street: 'chaoyang Wangjing... '}};}}
Now, the basic functions of the form are complete. We created a form in the panel, initialized user data in the component, and displayed on the page. On the page, we used ngModel to bind the data changes on the page to the component. At the same time, the name attribute is used to make all data in the form a FormControl object. In the method called for submission, the verification status and data of the form are obtained.
Verification and status of Form Controls
Next, we will add data verification. Angular2 provides us with several basic verification methods:
- Required: indicates that the data is required.
- Minlength: sets the minimum length of the field. The length is determined based on the string even if a number is entered.
- Maxlength: set the maximum length of the field.
- Pattern: Regular Expression Verification
Before using Angular verification, we must first disable the default browser verification. Otherwise, if an input is invalid, the submit button cannot be submitted. We add novalidate in form:
<form #userForm="ngForm" (ngSubmit)="logForm(userForm)" novalidate>
Then, we add verification to the name input box and display different prompts based on the verification results. In addition, to demonstrate the features of the Angular2 Form Control, add several prompts, the Code is as follows:
<Input type = "text" name = "name" [(ngModel)] = "user. name "# name =" ngModel "required minlength =" 3 "> <span * ngIf =" name. pristine "class =" label-primary "> not modified </span> <span * ngIf =" name. dirty "class =" label-warning "> modified </span> <span * ngIf =" name. valid "class =" label-success "> valid </span> <div [hidden] =" name. valid | name. pristine "class =" alert-danger "> <p * ngIf =" name. errors ?. Minlength "> the minimum name length is 3 </p> <p * ngIf =" name. errors ?. Required "> name required </p> </div>
First, we added two verifications on the input, required and minlength = "3 ".
Secondly, we use # name = "ngModel" to create a template reference variable, so that we can use name below to obtain reference of this form control (FormControl. The Form Control has some attributes, such as pristine, dirty, valid, and touched. These attributes are state types, indicating whether a certain state is true. In addition, the value of the control can be obtained using name. value. Finally, the verification error message results are stored in name. errors.
In the above Code, we use <span * ngIf = "name. pristine "class =" label-primary "> unmodified </span>: displays a lebel when the control value is not modified. Similarly, the corresponding labels are displayed when they are modified and verified to be valid.
Finally, the error messages for all verification results are saved in name. in errors, if there is no data verification error, the errors value is null. Therefore, in the above Code, we use name. errors ?. Minlength, which indicates that if errors is not null and errors. minlength is not empty, the information is displayed.
We can see that the form control will put the validator name as the key in errors for verification, and the corresponding value is true. We use this feature to display friendly error messages based on different results of control verification.
If we run our instance, we can find that for the name, if we clear its value, we find that there is only one error message, that is, we must enter the name. You may think that if the value is null and the length is smaller than 3 at this time, the minlength error should also be detected. However, after the first error is encountered, there will be no other verification.
In the name input box above, we use # name = "ngModel" to create a template reference variable, and then use it in the following template to obtain the Form Control. In fact, we can also directly use the previously defined reference to ngForm to obtain the status of all controls in this form. For example, we use the following method for phone calls:
<Input type = "text" name = "mobile" [ngModel] = "user. mobile "required minlength =" 11 "maxlength =" 11 "> <span * ngIf =" userForm. controls. mobile ?. Pristine "class =" label-primary "> not modified </span> <span * ngIf =" userForm. controls. mobile ?. Dirty "class =" label-warning "> modified </span> <span * ngIf =" userForm. controls. mobile ?. Valid "class =" label-success "> valid </span> <div [hidden] =" userForm. controls. mobile ?. Valid | userForm. controls. mobile ?. Pristine "class =" alert-danger "> <p * ngIf =" userForm. controls. mobile ?. Errors ?. Minlength "> the telephone length must be 11 </p> <p * ngIf =" userForm. controls. mobile ?. Errors ?. Required "> you must enter the phone number </p> </div>
Here, we do not get the template reference for mobile, but use the reference of ngForm to get it:
userForm.controls.mobile?.pristine
When obtaining verification error results:
userForm.controls.mobile?.errors?.minlength
Note: This is used on mobile? This is because the form control is not initialized when ngIf is used to render elements on the page. If this is not added ?, An error occurs.
Define a style based on the verification status
In addition to the data on the control, Angular also adds css styles to the html element where the control is located based on the Status:
Therefore, we only need to define the relevant css to display different effects based on the status.
.ng-valid[required], .ng-valid.required { border-left: 5px solid #42A948; /* green */}.ng-invalid:not(form).ng-invalid:not(fieldset) { border-left: 5px solid #a94442; /* red */}
Combined with various css selectors, we can implement various display styles based on the status of the Form Control.
Get Form Control Data in components
Finally, let's look at how to get the status and results of these controls in the component. In the above, we added a submission method to ngForm:
<form #userForm="ngForm" (ngSubmit)="logForm(userForm)" novalidate>
In the component, the logForm (userForm) method is as follows:
logForm(theForm: NgForm) { if (theForm.invalid) { if (theForm.controls['name'].errors) { this.nameErrorMsg = 'name error:' + JSON.stringify(theForm.controls['name'].errors); } else { this.nameErrorMsg = null; } } console.log(theForm.value);}
In this method, theForm is the ngForm template reference instance and the type is NgForm.
If form verification fails, theForm. invalid is false.
TheForm. controls is all the controls in this form. If you want to obtain the name verification result, it is theForm. controls ['name']. errors.
In this way, we can obtain the data, verification status, and error information of All Form Controls in the component.
Reset form
In general, for new user information, we need to clear the current data, reset the status of the form, and wait for the user to re-enter. If we only clear the data, the verification errors will be detected. We need to reset the form controls to the unmodified status. This is quite simple in Angular2. It provides a reset method.
Add a reset button in it:
<Button (click) = "reset (userForm)"> reset </button>
Then in the component:
reset(theForm: NgForm) { theForm.reset(); return false;}
Note that we need to make this method return false so that it will not trigger the submit method.
In the official document, we also provide another technique to implement this reset, that is, to use ngIf on form:
<form #userForm="ngForm" (ngSubmit)="logForm(userForm)" novalidate *ngIf="active">
This form is created only when active is true.
Then, when resetting, set the active status to false so that the form will be destroyed and set to true in setTimeout mode. Then, the form will be created again, in this way, the reset effect is achieved.
Reset () {this. user ={// reset user data address :{}}; this. active = false; setTimeout () => this. active = true, 0); return false ;}
This is also a tip that can be used in some cases.
Summary
At this point, the basic usage of the template-driven form is roughly complete, and then summarize the basic features of the template-driven form:
- All Form Controls are defined in the template.
- All validators are added to the template.
- The status and Verification Result of the form data are displayed on the template by judging the status of the control data in the form.
- To test the code, you must use e2e (end-to-end) testing, that is, in the browser.
The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.