Angular Study Notes Five Form

1. Template driver

The control logic of the form is written in the component template, which is more suitable for simple form types.

(1) Create a simple form

  1. It needs to be introduced in the component class FormsModuleand define a submission method
import {
    
    Component} from '@angular/core';
import {
    
    FormsModule} from "@angular/forms";

@Component({
    
    
    selector: 'app-layout',
    templateUrl: './layout.component.html',
})

export class LayoutComponent {
    
    
    onSubmit(value: any) {
    
    
        console.log(value);
    }
}
  1. In the component template, by #myForm="ngForm"defining this form as Angulara form, you can use Angularthe features provided in the form. Bind the submit event to this form. For form controls, you need to set nameproperties as unique indexes and set ngModelproperties to achieve two-way data binding with the form object.
<form #myForm="ngForm" (submit)="onSubmit(myForm)">
    <input type="text" name="username" ngModel />
    <button type="submit">Submit</button>
</form>
  1. In the web page, enter a piece of text, click the submit button, and check that the submit event receives valuean ngFormobject, which contains form.valuethe data source of the two-way binding of the control. The properties of the form control nameserve as the keys and valuevalues ​​of the data source. Only the input value of the set ngModelcontrol will be recorded form.valuein
    Insert image description here

(2) Form grouping

When a large number of form items are needed, the form items can be managed in groups.

  1. In the component template, by ngModelFroupgrouping, the group name will be stored in the form object as a direct attribute name.
    Here, if the elements used for grouping are replaced ng-container, they will not be rendered into real elements.
<form #myForm="ngForm" (submit)="onSubmit(myForm)">
    <h3>用户信息</h3>
    <div ngModelGroup="user">
        名字:<input type="text" name="username" ngModel />
        年龄:<input type="number" name="age" ngModel />
    </div>
    <h3>车辆注册信息</h3>
    <div ngModelGroup="car">
        品牌:<input type="text" name="brand" ngModel />
        颜色:<input type="color" name="color" ngModel />
    </div>
    <button type="submit">Submit</button>
</form>
  1. Fill out the form and click Submit to view the console form.value:
    Insert image description here

(3) Form verification

AngularSeveral common validation rules provided by forms:

  • required required field
  • minlength minimum length
  • maxlength maximum length
  • pattern regular verification
  1. In the component template, add the rules that need to be verified on the form items that need to be verified.
名字:<input type="text" name="username" ngModel pattern="\d" maxlength="10"/>
年龄:<input type="number" name="age" ngModel required/>
  1. In the component class, when submitting, you can form.validcheck whether the form verification passes through the attribute (Boolean)
onSubmit(form: any) {
    
    
   console.log(form.valid); 
}
  1. For the submit button, you can restrict the click when form.valid is false. !myForm.validcan be written asmyForm.invalid
<button type="submit" [disabled]="!myForm.valid">Submit</button>
  1. When the verification fails, you can HTMLadd prompt information in
    . When you need a single form item to display its own prompt information, you must first get the individual form item and #username=’ngModel‘get the form item;
    usernamethe type is to get the form item NgMdelbased on the attribute. touchedClick or enter;
    touchedthe property will change when inputthe mouse is moved into and out of the box true;
    invalidthe property gets whether the form item fails the verification;
    errorsthe property stores the information of all failed verification items.
名字:<input #username='ngModel' type="text" required name="username" pattern="\d*" ngModel maxlength="10"/>
<button type="submit">Submit</button>
<div *ngIf="username.touched && username.invalid && username.errors" style="color: red">
    <div *ngIf="username.errors['required']">用户名必填</div>
    <div *ngIf="username.errors['pattern']">用户名必须是数字</div>
    <div *ngIf="username.errors['maxlength']">用户名最大长度为10</div>
</div>

2. Model driven

The control logic of the form is written in the component class, which is more flexible for operations such as form verification and is more suitable for complex forms.
A model-driven form is an FormGroupinstance of a class that can validate the form as a whole; each form item is an FormControlinstance of a class that can validate individual form items and monitor changes to form values.

(1) Create a form

  1. In the module to which the component belongs, ReactiveFormsModulethe module needs to be introduced and added to importsthe array
import {
    
    ReactiveFormsModule} from "@angular/forms";
@NgModule({
    
    
    ...
    imports: [
        ...
        ReactiveFormsModule
    ],
    ...
})
  1. In the component class, you need to introduce the required modules, define the current form as an FormGroupinstance of the class, and define each form item as FormControlan instance of the class
...
import {
    
    FormGroup, FormControl} from "@angular/forms";
...
export class LayoutComponent {
    
    
    public form: FormGroup = new FormGroup({
    
    
        username: new FormControl(),
        age: new FormControl(),
    });
    onSubmit() {
    
    
        console.log(this.form);
    }
}
  1. In the component template, the current form uses formGroupattributes to bind the instances defined in the component class FormGroup, and the form items use formControllNamebinding to each FormControlinstance; formGroupthe binding is an object, so brackets are needed; formControllNamethe binding is a string, so no need Square brackets.
<form [formGroup]="form" (submit)="onSubmit()">
    名字:<input type="text" formControlName="username"/>
    年龄:<input type="number" formControlName="age"/>
    <button type="submit">Submit</button>
</form>
  1. Enter the form items, click Submit, and take a look at the output this.formdata structure.
    Insert image description here

(2) Form grouping

  1. In the component class, form grouping can be achieved by FormGroupcreating an object inside the object.FormGroup
public form: FormGroup = new FormGroup({
    
    
    user: new FormGroup({
    
    
        username: new FormControl(),
        age: new FormControl(),
    }),
    car: new FormControl()
});
  1. In the component template, the group uses formGroupNamethe name of the binding group
<form [formGroup]="form" (submit)="onSubmit()">
    <ng-container formGroupName="user">
       名字:<input type="text" formControlName="username"/>
       年龄:<input type="number" formControlName="age"/>
    </ng-container>
    车辆:<input type="text" formControlName="car"/>
    <button type="submit">Submit</button>
</form>

(3) Dynamically create forms: FormArray

FormArrayUsed to dynamically add a set of form items. The entire form formneeds to be bound to an FormGroupinstance object. Within this instance object FormControl, objects (a single form item), FormGroupobjects (a group of form items), or FormArrayobjects (a group of dynamically added form items) can be placed.

  1. In the component class, FormGroupcreate an attribute in the instance object bound to the current form. The type is FormArray, and each element in it is one FormGroup. Initialize an element.
public carForm: FormGroup = new FormGroup({
    
    
    cars: new FormArray([
        new FormGroup({
    
    
            name: new FormControl(),
            power: new FormControl()
        })
    ])
});
  1. In component template
  • By formArrayNamebinding the property name of this object, two-way data binding between the template and object data FormArraycan be achieved .FormArray
  • FormArrayThe attribute of the instance controlsis an array that saves the data of the dynamically added form group. *ngForSince it is an array, it needs to be bound when rendering .
  • controlsEach item of is an FormGroupinstance object, so for each item, you need to use the attribute FormGroupNamebound to the current element.index
  • Each FormGroupinstance object and the form items inside it are all FormControlinstance objects, so you need to use FormControlNamethe binding attribute name.
<form [formGroup]="carForm" (submit)="onSubmit()">
    <div formArrayName="cars">
        <div *ngFor="let car of cars.controls; let i = index" [formGroupName]="i">
            <input formControlName="name" placeholder="Car name">
            <input formControlName="power" placeholder="Car power">
        </div>
    </div>
</form>
  1. FormArrayIt is suitable for dynamically adding form groups, so we need a button to trigger the operation of adding a form group. And, FormArraya method to add an element to the object. FormArrayThe object's pushmethods add FormArrayan element to the object.
<button (click)="addCar()">增加一组表单</button>
addCar() {
    
    
    const cars = this.carForm.get('cars') as FormArray;
    cars.push(new FormGroup({
    
    
        name: new FormControl(),
        power: new FormControl()
    }));
}
  1. For carsthis variable, you need to get it every time you add a form, so you can define it carsas a getformal variable. this.carsThis way you can access carsthe instance object directly FromArray.
get cars(): FormArray {
    
    
    return this.carForm.get('cars') as FormArray;
}
  1. When you need to delete a dynamically added form group, in the component template, each dynamically added FormGroupobject needs a delete button to trigger the delete operation and pass the current FormGroupobject indexto it; in the component class, you need to call the method FromArrayof the object removeAt, delete formGroupthe object at the specified index.
<div *ngFor="let car of cars.controls; let i = index" [formGroupName]="i">
    <input formControlName="name" placeholder="Car name">
    <input formControlName="power" placeholder="Car power">
    <button (click)="removeCar(i)">Remove</button>
</div>
removeCar(i: number) {
    
    
    // 从cars中删除第i个元素。比数组删除元素方便
    this.cars.removeAt(i);
}
  1. Add submitan event to print the current form when submittingvalue
    Insert image description here

(3) Form verification

  1. Built-in validator
    A built-in validator needs to be introduced in the component class; when using newkeywords to create FormControlobjects, the second parameter is passed an array of validation rules
    and is usernamedefined as geta type variable for easy access.
import {
    
    FormGroup, FormControl,Validators} from "@angular/forms";
public carForm: FormGroup = new FormGroup({
    
    
    username: new FormControl('', [
        Validators.required,
        Validators.minLength(4)])
})
get username() {
    
    
    return this.carForm.get('username') as FormControl;
}

In the component template, you can use usernameseveral properties to determine whether these validation rules have passed; you can carForm.validdetermine whether all the validation rules in the form have passed.

<form [formGroup]="carForm" (submit)="onSubmit()">
    <input type="text" formControlName="username">
    <div *ngIf="username.touched && username.invalid && username.errors">
        <div *ngIf="username.errors['required']">Username is required</div>
        <div *ngIf="username.errors['minlength']">Username must be at least 3 characters long</div>
    </div>
    <button type="submit" [disabled]="carForm.invalid">Submit</button>
</form>

(4) Custom form validator

Custom validators have the following rules:

  1. A custom validator is a TypeScriptclass
  2. The class contains specific verification methods. The verification method must be static and staticmodified.
  3. The verification method accepts a parameter controlof type , AbstractControlwhich is FormControlthe type of the instance object of the class.
  4. If the verification is successful, returnnull
  5. If the verification fails, an object is returned, which keyis the verification ID , indicating that the verification failed.valuetrue
(1) Customized synchronization form validator
1. Define synchronization validator
  • The validator is a tsclass, so it must be defined in a .ts file.
  • The parameter type received isAbstractControl
  • The returned parameter type isValidationErrors | null
  • Method names and identification names should be consistent
  • This class needs to be introduced by the component, so it needs to be exportexported
import {
    
    AbstractControl, ValidationErrors} from "@angular/forms";

export class MyValidators {
    
    
    static connotContainSpace(
        control: AbstractControl
    ): ValidationErrors | null {
    
    
        if (/\s/.test(control.value)) {
    
    
            return {
    
    connotContainSpace: true}
        }
        return null;
    }
}
2. Use sync validators
  • Introduce custom validator in component class
import {
    
    MyValidators} from "./MyValidators";
  • When the form item is new, pass in the validation rules that need to be used by the form item. Write the definition directly without calling it.
public carForm: FormGroup = new FormGroup({
    
    
    username: new FormControl('', [
        Validators.required,
        Validators.minLength(4),
        MyValidators.connotContainSpace])
})
  • Prompt in component template
<div *ngIf="username.touched && username.invalid && username.errors">
    <div *ngIf="username.errors['required']">Username is required</div>
    <div *ngIf="username.errors['minlength']">Username must be at least 3 characters long</div>
    <div *ngIf="username.errors['connotContainSpace']">用户名不能包含空格</div>
</div>
(2) Custom asynchronous form validator
1. Define an asynchronous validator
  • The type of the asynchronous validator return value is Promiseor Observable, and the result of this Promiseresolve isValidators | null
  • Asynchronous verification will only be performed after all synchronous verifications pass. If synchronous verification fails, asynchronous verification will not be performed.
// 异步验证器
static shouldBeUnique(
    control: AbstractControl
): Promise<ValidationErrors | null> {
    
    
    return new Promise((resolve, reject) => {
    
    
        setTimeout(() => {
    
    
            if (control.value === 'mosh') {
    
    
                resolve({
    
    shouldBeUnique: true})
            } else {
    
    
                resolve(null)
            }
        }, 2000)
    })
}
2. Use asynchronous validators
  • The asynchronous validator should be placed in formControlthe third parameter when the object is created.
  • Used in templates the same as built-in validators
public carForm: FormGroup = new FormGroup({
    
    
    username: new FormControl('', [
        Validators.required,
        Validators.minLength(5),
        MyValidators.connotContainSpace],
        MyValidators.shouldBeUnique)
})
3. Show verification status
  • formControlThe object has an attribute pending. During the execution of asynchronous verification, the attribute is true, otherwise it isfalse
<div *ngIf="username.pending">正在验证...</div>

(5) FormBuilder

  • FormBuilderIt is a class. Instance objects of this class can help us quickly create forms.
  • FormGroupYou can use the method to create an object formBuilder.group(). This method receives two parameters. The first parameter is controlsthe object composed of the form items. The second parameter is the verification rule optionsfor formGroupthe object. The verification rules written here are usually self- Define validation rules and receive them formGroupas parameters. You can define validation rules for all form items in the entire form. For example, two form items cannot be the same, etc.
  • FormControlYou can use the method to create formBuilder.control()an object. This method can accept three parameters. The first parameter is the default value of the form item. The second parameter is an array of synchronous form validators. The third parameter is an array of asynchronous form validators.
  • When creating FormControlan object, you can also directly use an array as a form item value. The array element list is the same as formBuilder.control()the parameter list of the above method.
constructor(private formBuilder: FormBuilder) {
    
    
}

public form:FormGroup = this.formBuilder.group({
    
    
    username: this.formBuilder.control(''),
    password: ['', [Validators.required, Validators.minLength(6)]],
})

(6) Common methods of model-driven forms

(1)patchValue
  • Set the value of the form control, you can set all, or you can set one
onPatchValue() {
    
    
    this.form.patchValue({
    
    
        username: 'mosh'
    })
}
(2)setValue
  • Set the values ​​of all form controls. It won't work if you don't set it all.
onSetValue() {
    
    
    this.form.setValue({
    
    
        username: 'meggie',
        password: '123456'
    })
}
(3)valueChanges
  • Event triggered when the value of a form control changes.
  • You need to obtain a certain form control that you want to monitor changes, and then register the listening function
  • subscribeThe parameters obtained in the subscription function are the modified values
ngOnInit() {
    
    
    this.form.get('username')?.valueChanges.subscribe(value => {
    
    
        console.log(value);
    })
}
(4)reset
  • Leave form content blank
onReset() {
    
    
   	this.form.reset();
}

Guess you like

Origin blog.csdn.net/weixin_45855469/article/details/130515587