AngualrAngular经验总结

Angular6 form表单相关

2018-07-12  本文已影响327人  桃之_夭夭_

一、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)
}

三、表单中常见的坑

  1. 表单中的input框回车就自动提交表单
    解决方法,在<form>标签上添加onkeypress="if(event.keyCode===13||event.which===13){return false;}"

  2. 表单中的button标签,如果不设置type,点击默认触发点击事件,除了提交按钮设置type='submit',其他button需要设置type='button'属性

  3. formGroup里面嵌套formGroup,点击提交的时候外层的能触发验证,但是内层的不能触发验证。解决方法:[formGroup] = "targetForm.controls['test']"改为formGroupName="test"

  4. 谷歌浏览器中,当input type=text与type=password相邻时,input框会自动填充用户名。解决方法为:设置两个form将两个input隔离开。如下:

<form>
    <input type="text"/>
</form>
<form>
    <input type="password"/>
</form>
  1. formGroup中嵌套的formArray,formArray中嵌套formGroup,submit的时候,判断this.targetForm.valid时,formArray内部若不能校验,则需要查询formArray用法是否有问题,需要设置formArrayName="testArr",且子元素需要设置formGroupName = 'i',形如上栗(3);若formArray中是formControl,则子元素直接设置formControlName = 'i' 就可以了
上一篇下一篇

猜你喜欢

热点阅读