angular13源码分析(表单查缺补漏一)

QQ20220113140932.png

FormControl


  maxLength(): ValidatorFn {
    return (control: AbstractControl): ValidationErrors | null => {
      // 给个报错信息
      if (control.value === '333') {
        return {sex: true};
      }
      return null;
    };
  }
  sex: FormControl = new FormControl({value: '111', disabled: false}, [this.maxLength()]);
<input type="text" [formControl]="sex">

getError 与hasError

返回类型不一样
getError :any
hasError :boolean

  formModel!: FormGroup;
     ngOnInit(): void {
        this.formModel = new FormGroup({
          login: new FormControl('', [this.maxLength()]),
          passwords: new FormGroup({
            password: new FormControl()
          })
        });

        console.log(this.formModel.getError('sex', ['login']))
      }
      this.validateForm.getError('required', ['sex'])
	  this.validateForm.get('sex')!.getError('required')
      this.validateForm.getError('required',['loginGroup','add1'])
	  this.validateForm.getError('required','loginGroup.add1')

getError/hasError 第二个参数可以是一个数组, 进行属性查询

updateValueAndValidity

重新计算控件的值和验证状态。

onlySelf: 当为true时,只自身被触发但是父级不会被触发。当为false或未提供时,更新所有直接的祖先。默认是false

emitEvent: 默认为truestatusChangesvalueChanges可观察对象都会在控件更新时发出带有最新状态和值的事件。当为false时,不触发任何事件。

      this.form.updateValueAndValidity({emitEvent: false});

get

    get(path: Array<string | number> | string): AbstractControl | null;
this.form.get('xxx')!.value
this.form.get(['aaa','bbb'])!.value
this.form.get('aaa.bbb').value    // 还可以这样拿值

数组
 const g = new FormGroup({'array': new FormArray([new FormControl('111')])});
 g.get(['array', 0])!.value
 // 111

设置报错信息

setErrors

control.get('timeEnd').setErrors(null);
control.setErrors({required: true});
// 查看报错信息
this.formModel.get('login')!.errors

array-insert

FormArray 数组中,索引插入一个

    this.formModel = new FormGroup({
      sexArr: new FormArray([])
    });
    const arr=this.formModel.get('sexArr') as FormArray;
    arr.push(new FormControl(1))
    arr.push(new FormControl(2))
    arr.insert(1,new FormControl(3))
    // [1, 3, 2]

插入的时候, 第二个参数也可以添加配置
      a.push(c1, {emitEvent: false});

setControl

arr.push(new FormControl(1))
arr.push(new FormControl(2))
arr.setControl(1,new FormControl(4))
// [1,4]
this.formModel.setControl('login',new FormControl('333'))
// {login: '333'}

异步校验器

  validatorFnOne = (value: any) => {
    console.log(value);
    return {controlsOne: true};
  };
  asyncValidatorFn = (value: any) => of(this.validatorFnOne(value));

	this.formModel = new FormGroup({
      login: new FormControl('1212', null, this.asyncValidatorFn),
      sex1: ['', {
        updateOn: 'blur',
        validators: [
          (val: AbstractControl) => ({sexError: true})
        ]
      }],
    });

getRawValue

包括所有的值, 包括禁用的

  this.formModel = new FormGroup({
      login: new FormControl('111', null, this.asyncValidatorFn),
      loginOne: new FormControl('222'),
    });
    this.formModel?.get('loginOne')!.disable();
    console.log(this.formModel.value);
   // {login:111}
    console.log(this.formModel.getRawValue());
   // {login:111,loginOne:222}

reset

a.setValue(['new value', 'new value']);
a.reset([{value: 'initial value', disabled: false}, '']);
a.value
//['initial value', '']
this.validateForm.reset({sex:{value:'2232323',disabled:true}})

reset() 执行,

  • 会保留之前的禁用状态
  • valueChangestatusChanges 会被执行

pristine

如果用户尚未更改 UI 中的值(默认为true)

a.pristine  //true
a.markAsDirty(); // 触发了, 或者输入改变值
a.pristine  // false
a.reset();  // 重置状态
a.pristine  // true

dirty

是否更改了 UI 中的值

pristine的值相反(默认是false)

untouched

如果控件未被标记为已触摸(默认为true)

我们发现当我们失去焦点才会触发状态的修改blur或者markAsTouched()

a.untouched  //true
a.markAsTouched(); // 触发了, 或者输入改变值
a.untouched  // false
a.reset();  // 重置状态
a.untouched  // true

touched

如果控件标记为 则为真touched

untouched 相反

报错的状态

// 默认
g.valid   // true
g.errors  // null
g.setErrors({required: true}) // 设置报错
g.valid   // false
g.errors  // {required: true}

pending

这个我还不清楚实用的点

默认为false 校验的状态

markAsPending(opts: { onlySelf?: boolean; emitEvent?: boolean; } = {}): void
c.markAsPending();
c.pending   // true

校验

interface AbstractControlOptions {
    /**
     * @description
     * The list of validators applied to a control.
     */
    validators?: ValidatorFn | ValidatorFn[] | null;
    /**
     * @description
     * The list of async validators applied to control.
     */
    asyncValidators?: AsyncValidatorFn | AsyncValidatorFn[] | null;
    /**
     * @description
     * The event name for control to update upon.
     */
    updateOn?: 'change' | 'blur' | 'submit';
}
第二个,第三个
validatorOrOpts?: ValidatorFn | ValidatorFn[] | AbstractControlOptions | null,
asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[] | null);

status

a.status   // VALID
a.disabled // false

a.disable();

a.status   // DISABLED
a.disabled // true

a.enable();
a.status   // VALID
a.disabled // false

FormBuilder

export class ThreeControlComponent implements OnInit {
  validateForm!: FormGroup;

  constructor(private fb: FormBuilder) { }
  ngOnInit(): void {
        this.validateForm = this.fb.group({
          sex: ['111'],
          login: [{value: 'xxxxx', disabled: false}, this.validatorFn,this.asyncValidatorFn],
          a: this.fb.array([
            	    'one',
                    ['two', this.validatorFn, this.validatorFnOne],
                    {value: 'three', disabled: false},
                    [{value: 'four', disabled: false},this.validatorFn, this.validatorFnOne],
                    this.fb.control('xxx'),
                    this.fb.control({value:'xxx',disabled:false}),
     		 ])
        });
  }
}

updateOn 更新策略

updateOn:FormHooks
可能的值:'change'| 'blur'| 'submit' 默认值:'change'
案例:
 this.validateForm = this.fb.group({
      sex1: ['', {updateOn: 'blur'}],
 })
// 我们发现失去焦点的时候会触发
    this.validateForm.get('sex1')!.valueChanges.subscribe(console.log)
// 查看当前的更新方式
this.validateForm.get('sex1')!.updateOn
// blur
如果有更新策略,那么第二个参数
{
    validators:[],
    asyncValidators:[],    
    updateOn:'blur'
}

setValidators/setAsyncValidators

设置校验方式

 validatorFnOne = (value: any) => {
    // console.log(value);
    return {controlsOne: true};
  };
  asyncValidatorFn = (value: any) => of(this.validatorFnOne(value));

       this.validateForm.get('sex1')!.setValidators([Validators.required])

       this.validateForm.get('sex1')!.setAsyncValidators([this.asyncValidatorFn]);

dirty

当通过 UI 更改控件的值时,控件会变dirty , 默认为false

this.validateForm.get('sex1')!.dirty   // false
this.validateForm.get('sex1')!.markAsDirty();
this.validateForm.get('sex1')!.dirty  // true

windowDuration.invalid && (windowDuration.dirty || windowDuration.touched)

addControl

    this.validateForm = this.fb.group({
      sex1: ['', {updateOn: 'blur'}],
    });
this.validateForm.addControl('two1',new FormControl('1111'),{})

removeControl

this.validateForm.removeControl('sex')
g.removeControl('two', {emitEvent: false});

contains

查看表单是否有这个控件,默认为false

this.validateForm = this.fb.group({
      sex: ['111', [Validators.required]],
    });

    console.log(this.validateForm.contains('sex')); //true

通过dom修改表单的值,触发更新

<form [formGroup]="validateForm">
  <input type="text" formControlName="sex" #sex>
</form>
import {ɵgetDOM as getDOM} from '@angular/common';

export class ThreeControlComponent implements OnInit, AfterViewInit {
    dispatchEvent(element: any, eventType: any): void {
        const evt: Event = getDOM().getDefaultDocument().createEvent('Event');
        evt.initEvent(eventType, true, true);
        getDOM().dispatchEvent(element, evt);
      }

  ngAfterViewInit() {
    this.sex.nativeElement.value='111111111';
    setTimeout(()=>{
      this.dispatchEvent(this.sex.nativeElement, 'input');
      console.log(this.validateForm.value);
    })
  }
}

本质是因为DOM的修改,不会触发脏检查, 需要通过自定义事件进行触发脏检查机制, 从而更新

form表单完整版本

<form [formGroup]="validateForm">
  <input type="text" formControlName="sex">
<!--  对象集合-->
  <ng-container formGroupName="sexGroup">
    <input type="text" formControlName="sexOne">
  </ng-container>
<!--  数组集合-->
  <ng-container formArrayName="sexArr">
    <ng-container *ngFor="let item of sexArrControl.controls;let index=index">
      <ng-container [formGroupName]="index">
        <input type="text" formControlName="sexOne">
        <input type="text" formControlName="sexTwo">
      </ng-container>
    </ng-container>
  </ng-container>
</form>
export class ThreeControlComponent implements OnInit, AfterViewInit, AfterContentInit {
  validateForm!: FormGroup;
  constructor(private fb: FormBuilder) { }
  ngOnInit(): void {
    this.validateForm = this.fb.group({
      sex: ['111'],
      sexGroup: this.fb.group({
        sexOne: ['222']
      }),
      sexArr: this.fb.array([])
    });
    this.sexArrControl.push(this.sexObj)
  }

  get sexObj(): FormGroup {
    return this.fb.group({
      sexOne: ['a'],
      sexTwo: ['b'],
    })
  }

  get sexArrControl(): FormArray {
    return this.validateForm.get('sexArr') as FormArray;
  }
}
posted @ 2022-01-13 14:12  猫神甜辣酱  阅读(209)  评论(0编辑  收藏  举报