angular11源碼探索十三[表單基礎篇二]

statusChanges

statusChanges: Observable 數組

每次驗證的狀態,參數 status異步

new FormControl({value: '', disabled: true} 禁用也能夠這樣寫

當咱們手動設置報錯ui

const login = new FormControl('someLogin');
      login.setErrors({
        notUnique: true
      });
login.valid //false, 是否經過校驗
login.setValue('aaa')
login.valid //true

get查詢方式this

profileForm: FormGroup = new FormGroup({
    address: new FormGroup({
      name1: new FormControl()
    })
  });
this.profileForm.get('address.name1');
this.profileForm.get(['address', 'name1']);
兩種形式等價

getError/hasError 區別

查找方式雙向綁定

get('xxx')
get('aaa.bbb')
get(['aaa','bbb'])
get(['aaa',0]) // 數字就是索引

hasError 報錯查找code

this.profileForm.get(['address','name1'])?.setErrors({aaa:true})// 設置報錯
    console.log(this.profileForm.get(['address', 'name1'])?.hasError('aaa'));
		等價
    console.log(this.profileForm?.hasError('aaa', ['address', 'name1']));// true

源碼orm

getError(errorCode: string, path?: Array<string|number>|string): any {
    const control = path ? this.get(path) : this;
    return control && control.errors ? control.errors[errorCode] : null;
  }

  hasError(errorCode: string, path?: Array<string|number>|string): boolean {
    return !!this.getError(errorCode, path);
  }

卻別應該是返回類型不同吧,並且二者本質上就是父子關係,blog

上個小案例索引

let aa = this.profileForm.get('firstName') as FormControl;
    aa.setErrors({'aaa': '333'});
    console.log(aa.getError('aaa'));// 333
    console.log(aa.hasError('aaa'));// true

addControl 添加生命週期

(this.profileForm.get('address') as FormGroup).addControl('newControl', new FormControl(''));
    this.profileForm.addControl('name1',new FormControl())
    console.log(this.profileForm.value);

removeControl

this.profileForm.removeControl('address')

當刪除或者增長的時候,頁面沒有生效,其實應該在OnInit 生命週期中添加

ngModel雙向綁定

<input type="text" [(ngModel)]="sex" (ngModelChange)="changeA($event)">

校驗器

pristine   爲修改UI中的值,默認爲true     乾淨
dirty       修改過UI的值,默認爲false     髒的   
		兩個的默認值時相反的
touched     相似觸碰,失去焦點,默認是false
untouched  未接觸,默認爲true
異步驗證的時候,表單控件進入 pending狀態,默認false,並使用它提供有關正在進行的驗證操做的視覺反饋
促發每個子項是否是純潔的
.markAsDirty()   // pristine   dirty  通常用這個
促發每個子項touched是否動過
.markAsTouched/
有效性(就是是否禁用)
    VALID: 該控件經過了全部有效性檢查。

    INVALID 該控件至少有一個有效性檢查失敗了。

    PENDING:該控件正在進行有效性檢查,處於中間狀態。

    DISABLED:該控件被禁用,豁免了有效性檢查。
是否經過校驗
.valid
顯示報錯信息
.errors

通常第二個參數用於校驗,給數組總體添加校驗

//第一個參數不能與aaa
function simpleValidator(c: AbstractControl): ValidationErrors|null {
  //c.get([0]) 和 c.at(0) 相似
  return c.get([0])!.value === 'aaa' ? null : {'broken': true};
}
//第一個參數必須傳
function arrayRequiredValidator(c: AbstractControl): ValidationErrors|null {
  return Validators.required(c.get([0]) as AbstractControl);
}

  this.nameArr.valueChanges.subscribe(res => {
      //是否經過校驗
      console.log(this.nameArr.valid);
      // 報錯信息
      console.log(this.nameArr.errors);
    })

nameArr: FormArray = new FormArray([
    new FormControl('bb'),
  ],
    [simpleValidator,arrayRequiredValidator]
  )

pending

異步驗證的時候,表單控件進入 pending狀態,默認false,並使用它提供有關正在進行的驗證操做的視覺反饋

function arrayRequiredValidator(c: AbstractControl): ValidationErrors | null {
  return of({name1: true}).pipe(delay(500))
}

 this.profileForm = new FormGroup({
      firstName: new FormControl('xxx', null!, arrayRequiredValidator),
 })
   let aa = this.profileForm.get('firstName') as FormControl;
    console.log(aa.pending);// true
    of(null).pipe(delay(1000)).subscribe(_ => {
      console.log(this.profileForm.get('lastName').pending);// false

    })

markAsPending() 手動設置

console.log(this.profileForm.get('lastName').pending);//true
    this.profileForm.get('lastName').markAsPending()
    console.log(this.profileForm.get('lastName').pending);// false

	默認直屬父級也會被修改成true
		c = new FormControl('value');
		g = new FormGroup({'one': c});
		c.markAsPending();
		g.pending	//true
源碼
  markAsPending(opts: {onlySelf?: boolean, emitEvent?: boolean} = {}): void {
    (this as {status: string}).status = PENDING;

    if (opts.emitEvent !== false) {
      (this.statusChanges as EventEmitter<any>).emit(this.status);
    }

    if (this._parent && !opts.onlySelf) {
      this._parent.markAsPending(opts);
    }
  }

校驗器源碼

function isEmptyInputValue(value: any): boolean {
  // 這裏咱們不檢查字符串,因此它也適用於數組
  return value == null || value.length === 0;
}
function hasValidLength(value: any): boolean {
  // 判斷有值得
  return value != null && typeof value.length === 'number';
}

疑問爲何有時候能夠寫單個值,有時候寫數組,由於他是第二個參數,多個就寫數組,單個就直接寫單個值就好了

min
最小值,輸入number 比較大小
const control = new FormControl(2, Validators.min(3))
//actual 當前值
console.log(control.errors); // {min: {min: 3, actual: 2}} 

const control = new FormControl(16, Validators.max(15));
console.log(control.errors); // {max: {max: 15, actual: 16}}
能夠用來限制min max的number 值

上個源碼吧

static max(max: number): ValidatorFn {
    return (control: AbstractControl): ValidationErrors|null => {
      if (isEmptyInputValue(control.value) || isEmptyInputValue(max)) {
        return null;  // 不要驗證空值來容許可選控件
      }
      const value = parseFloat(control.value);
      // 不是NaN而後比較大小
      return !isNaN(value) && value > max ? {'max': {'max': max, 'actual': control.value}} : null;
    };
  }
相關文章
相關標籤/搜索