一、form中使用的input, select等均不建议使用ngModel绑定变量,因为Angular7会移除form中的这个指令,如果在6中使用则会报警告,直接使用formControl或者formControlName绑定form即可,如下
<form [formGroup]="targetForm" (ngSubmit)="save()" onkeypress="if(event.keyCode==13||event.which==13){return false;}">
<div>
<label>
姓名
</label>
<mat-form-field [floatLabel]="'never'">
<input matInput autocomplete="username" disableautocomplete type="text" name="username" formControlName="username" required>
</mat-form-field>
</div>
<div>
<button mat-button type="submit" class="sure">保存</button>
</div>
</form>
ts文件中targetForm定义如下:
targetForm
constructor(private fb: FormBuilder) {
this.targetForm = this.fb.group({
userName: ['王XX', Validators.required],
})
}
提交表单的时候,可以直接从刚刚定义的targetForm中取到value值,然后对应提交
二、FormControl,FormGroup和FormArray
1、三者中FormControl属于子元素,FormGroup和FormArray可任意嵌套这三个元素
(1)FormGroup中嵌套FromControl。这是最常见的形式,上述示例中就是这种格式
(2)FormGroup中嵌套FormGroup。
这种格式一般是表单中某些项和某一项有关联关系时使用,可以通过addControl来动态添加,举个栗子:
html
<form [formGroup]="targetForm" (ngSubmit)="save()" onkeypress="if(event.keyCode==13||event.which==13){return false;}">
<div>
<label>
职业
</label>
<mat-form-field [floatLabel]="'never'" class="dialog-input">
<mat-select placeholder="请选择" formControlName="profession"
(selectionChange)="changeProfession($event)" required>
<mat-option *ngFor="let item of professions" [value]="item">
{{ item }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div *ngIf="targetForm.get('profession').value === 'teacher'" formGroupName="teacher">
<div>
<label>
学校
</label>
<mat-form-field [floatLabel]="'never'">
<input matInput autocomplete="school" disableautocomplete type="text" name="school" formControlName="school" required>
</mat-form-field>
</div>
<div>
<label>
年级
</label>
<mat-form-field [floatLabel]="'never'">
<input matInput autocomplete="grade" disableautocomplete type="text" name="grade" formControlName="grade" required>
</mat-form-field>
</div>
</div>
<div>
<button mat-button type="submit" class="sure">保存</button>
</div>
</form>
ts,当选择职业为teacher时
constructor(private fb: FormBuilder){}
this.targetForm = fb.group({
profession: ['', Validators.required],
})
changeProfession(event) {
const {value} = event
if(value === 'teacher') {
const fbGroup = this.fb.group({
school: ['xxx', Validators.required],
grade: ['', Validators.required]
})
// contains方法判断是否包含teacher control
if(!this.targetForm.contains('teacher')) {
this.targetForm.addControl('teacher', fbGroup)
}
} else{
// 删除targetForm中的teacher control
this.targetForm.removeControl('teacher')
}
}
(3)FormGroup中嵌套FormArray,且FormArray中嵌套FormGroup。一般用于对表单中数组的动态处理,举个栗子:
html文件
<div>
<label>
职业
</label>
<mat-form-field [floatLabel]="'never'" class="dialog-input">
<mat-select placeholder="请选择" formControlName="profession"
(selectionChange)="changeProfession($event)" required>
<mat-option *ngFor="let item of professions" [value]="item">
{{ item }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
<ng-container *ngIf="targetForm.get('profession').value === 'teacher'">
<mat-icon style="color: #3CB371" (click)="addAction()">add</mat-icon>
<div formArrayName="testArr">
<ng-container *ngFor="let test of testArr.controls;let index = index" [formGroupName]="i">
<div class="col-5">
<mat-form-field class="w-100">
<mat-form-field class="w-100">
<input autocomplete="off" disableautocomplete matInput type="text" formControlName="key" placeholder="key">
</mat-form-field>
</mat-form-field>
</div>
<div class="col-5">
<mat-form-field class="w-100">
<input autocomplete="off" disableautocomplete matInput type="text" formControlName="value" placeholder="value">
</mat-form-field>
</div>
<div class="m-auto text-right">
<mat-icon style="color: #3CB371" class="cancelMatIcon" (click)="removeAction(index)">
delete
</mat-icon>
</div>
</ng-container >
</div>
</ng-container>
ts文件
constructor(private fb: FormBuilder){
this.targetForm = fb.group({
profession: ['', Validators.required],
testArr: fb.array([])
})
}
get testArr() {
return this.targetForm.get('testArr') as FormArray
}
// 新增
addAction() {
const fb = this.fb
const fbGroup = fb.group({
key: ['', Validators.required],
value: ['', Validators.required],
})
this.targetForm.controls.testArr.push(fbGroup)
}
// 删除
removeAction(index) {
const arr = this.targetForm.get('testArr') as FormArray
arr.removeAt(index)
}
三、表单中常见的坑
-
表单中的input框回车就自动提交表单
解决方法,在<form>标签上添加onkeypress="if(event.keyCode===13||event.which===13){return false;}" -
表单中的button标签,如果不设置type,点击默认触发点击事件,除了提交按钮设置type='submit',其他button需要设置type='button'属性
-
formGroup里面嵌套formGroup,点击提交的时候外层的能触发验证,但是内层的不能触发验证。解决方法:[formGroup] = "targetForm.controls['test']"改为formGroupName="test"
-
谷歌浏览器中,当input type=text与type=password相邻时,input框会自动填充用户名。解决方法为:设置两个form将两个input隔离开。如下:
<form>
<input type="text"/>
</form>
<form>
<input type="password"/>
</form>
- formGroup中嵌套的formArray,formArray中嵌套formGroup,submit的时候,判断this.targetForm.valid时,formArray内部若不能校验,则需要查询formArray用法是否有问题,需要设置formArrayName="testArr",且子元素需要设置formGroupName = 'i',形如上栗(3);若formArray中是formControl,则子元素直接设置formControlName = 'i' 就可以了
网友评论