angular2 學習筆記 ( Form 表單 )

更新: 2019-08-17 css

上次提到說經過 custom value accessor 來實現 uppercase 不過遇到 material autocomplete 就撞牆了. html

由於 material 也用了 custom value accssor ... html5

那就不要那麼麻煩了,綁定一個 blur 事件,在用於 blur 的時候才變 uppercase 唄. git

另外說一下 number validation, github

ng 的 input type=number 是沒法驗證的 ajax

由於原生的 input type=number 在 invalid 的時候 value 是 empty string api

而 ng 遇到 empty string 會直接返回 null數組

因此若是咱們想讓用戶知道 number invalid 咱們得修改 value accessor 服務器

registerOnChange(fn: (_: number | null) => void): void {
  this.onChange = (e: Event) => {
    const input = e.target as HTMLInputElement;
    let value: number | null;
    if (input.validity.badInput) {
      value = NaN;
    } else if (input.value === '') {
      value = null;
    } else {
      value = parseFloat(input.value);
    }
    console.log(value);
    fn(value);
  };
}

讓它返回 nan 才能夠。angular2

 

 

更新: 2019-07-31

今天想作一個 input uppercase,就是用戶輸入 lowercase 自動變成 uppercase 的 input 

ng1 的作法是用 formatter 和 parser 來實現,可是 ng2 沒有這個東西了。

https://github.com/angular/angular/issues/3009

2015 年就提了這個 feature issue,可是直到今天有沒有好的 idea 實現。

formatter parser 對 validation 不利,並且難控制執行順序. 

目前咱們惟一能作的就是本身實現一個 value accessor 來處理了.

原生的 input, Angular 替咱們實現了 DefaultValueAccessor,因此 input 天生就能夠配合 FormControl 使用.

@Directive({
  selector:
      'input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]',
  // TODO: vsavkin replace the above selector with the one below it once
  // https://github.com/angular/angular/issues/3011 is implemented
  // selector: '[ngModel],[formControl],[formControlName]',
  host: {
    '(input)': '$any(this)._handleInput($event.target.value)',
    '(blur)': 'onTouched()',
    '(compositionstart)': '$any(this)._compositionStart()',
    '(compositionend)': '$any(this)._compositionEnd($event.target.value)'
  },
  providers: [DEFAULT_VALUE_ACCESSOR]
})
export class DefaultValueAccessor implements ControlValueAccessor {

源碼裏能夠看到,Angular 監聽的是 oninput 還有 compositionstart 這個是爲了處理中文輸入

上網找了一些方法,有人說監聽 keydown or keypress 而後 set event.target.value 

有些人說監聽 input. 

但其實這 2 個都是不對的. 

咱們知道用戶輸入時, 事件觸發的順序時 keydown -> keypress -> input -> keyup. 若是用戶長按不放,keydown, keypress, input 會一直觸發, keyup 則只會觸發一次. 

而 keydown, keypress 觸發時,咱們只能獲取到 event.key 和 event.code 當時的 event.target.value 依然時舊的值. 

咱們監聽 oninput 也不行,由於 Angular 的指令會更快的執行. 

因此惟一咱們能作的是寫一個 CustomValueAccessor 去替換掉 DefaultValueAccessor 

每個組件只能容許一個 value accessor. 選擇的順序是 custom 優先, builtin 第二, default 第三

下面這些是 build in 的, default 指的是 input text 和 textarea 

const BUILTIN_ACCESSORS = [
  CheckboxControlValueAccessor,
  RangeValueAccessor,
  NumberValueAccessor,
  SelectControlValueAccessor,
  SelectMultipleControlValueAccessor,
  RadioControlValueAccessor,
];

因此只要咱們寫一個 input directive 實現 custom value accessor 那麼咱們的就會優先選中執行. 而 default value accessor 就不會被執行了.

這樣咱們就實現咱們要的東西了。

 

 

更新 : 2019-07-17

async validator 

終於有需求要用到了. 

async 的問題主要就是發的頻率, 用戶一直輸入, 一直髮請求去驗證傷服務器性能. 

有 2 種作法, 一是用 updateOn: blur,這個很牛, 一行代碼搞定, 可是未必知足體驗. 

另外一種是用返回 obserable + delay, 能夠看下面這個連接 

https://stackoverflow.com/questions/36919011/how-to-add-debounce-time-to-an-async-validator-in-angular-2

關鍵就是 ng 監聽到 input 事件後會調用咱們提供的方法, 而後 ng 去 subscribe 它等待結果. 

而第二個 input 進來的時候 ng 會 unsubscribe 剛纔那一次, 因此咱們把請求寫在 delay 以後, 一旦被 unsubscribe 後就不會發出去了. 

沒有看過源碼, 可是推測 ng 內部是用 switchmap 來操做的, 因此是這樣的結果. 很方便哦.

另外, 只有當普通的 validation 都 pass 的狀況下, ng 纔會檢查 async 的 validation 哦.

 

當 async validator 遇到 OnPush, view 的更新會失效. 

https://github.com/angular/angular/issues/12378

解決方法是加一個 tap markForCheck

asyncValidators: (formControl: FormControl): Observable<ValidationErrors | null> => {
  return of([]).pipe(delay(400), switchMap(() => {
    return from(this.customerService.checkCustomerNameUniqueAsync({ name: formControl.value })).pipe(map((isDuplicate) => {
        return isDuplicate ? { 'unique': true } : null;
    }), tap(() => this.cdr.markForCheck()));
  }));

或者使用 (statusChanges | async) === 'PENDING'

 

 

 

更新 : 2019-07-16 

動態驗證簡單例子 

ngOnInit() {
  this.formGroup = this.formBuilder.group({
    name: [''],
    email: ['']
  });
  this.formGroup.valueChanges.subscribe((value: { name: string, email: string }) => {
    if (value.name !== '' || value.email !== '') {
      this.formGroup.get('name').setValidators(Validators.required);
      this.formGroup.get('email').setValidators(Validators.required);

      // this.formGroup.updateValueAndValidity({ emitEvent: false }); // 調用 formGroup 是不足夠的, 它並不會去檢查 child control
      this.formGroup.get('name').updateValueAndValidity({ emitEvent: false }); // 這個就有效果, 可是記得要放 emitEvent false, 否則就死循環了 
      // 最後.. 這裏不須要調用 ChangeDetectorRef.markForCheck() view 也會更新
    }
  });
}

 

 

 

更新 : 2019-05-25

disabled 的 control 不會被歸入 form.valid 和 form.value 裏, 這個和 html5 行爲是一致的. 

https://github.com/angular/angular/issues/11432   

 

更新 : 2018-02-13 

valueChanges and rxjs for filter first value 
需求是這樣的 
let fc = new FormControl('');   
fc.valueChanges.subscribe(v => console.log(v));
fc.setValue(''); // '' to '' 沒有必要觸發
fc.setValue('a'); // '' to a 觸發 

但是結果 2 個都觸發了.

那這樣試試看 : 

fc.valueChanges.pipe(distinctUntilChanged()).subscribe(v => console.log(v));

結果仍是同樣. 

問題在哪裏呢 ? 

首先 ng 的 formControl 看上去想是 BehaviorSubject 由於它有 default 值, 可是行爲卻像是 Subject. 由於 

let fc = new FormControl('dada');   
fc.valueChanges.subscribe(v => console.log(v)); //並無觸發

雖然以前的代碼問題出在, 沒有初始值, 因此 distinctUntilChanged 就發揮不了做用了 

咱們須要用 startWith 告訴它初始值

let fc = new FormControl('dada');
fc.valueChanges.pipe(startWith('dada'), distinctUntilChanged(), skip(1)).subscribe(v => console.log(v));
fc.setValue('dada'); // 不觸發
fc.setValue('dada1'); //觸發了

startWith 會立刻輸入一個值, 而後流入 distinct, distinct 會把值對比上一個(目前沒有上一個), 而後記入這一個, 在把值流入 skip(1), 由於咱們不要觸發初始值, 因此使用了 skip, 若是沒有 skip 這時 subscribe 會觸發. (startWith 會觸發 subscribe)

這樣以後的值流入(不通過 startWith 了, startWith 只用一次罷了), distinc 就會和初始值對比就是咱們要的結果了. 

若是要在加上一個 debounceTime, 咱們必須加在最 startWith 以前. 

pipe(debounceTime(200), startWith(''), distinctUntilChanged(), skip(1))

一旦 subscribe startWith 輸入值 -> distinct -> skip 

而後 setValue -> debounce -> distinc -> 觸發 ( startWith 只在第一次有用, skip(1) 也是由於已經 skip 掉第一次了)

 

 

 

更新 : 2018-02-10

form.value 坑

let ff = new FormGroup({ 
    name : new FormControl('')
});
ff.get('name')!.valueChanges.subscribe(v => {
  console.log(v); // 'dada'
  console.log(ff.value); // { name : '' } 這時尚未更新到哦 
  console.log(ff.getRawValue())  // { name : 'dada' }
});
ff.get('name')!.setValue('dada');
console.log(ff.value); // { name : 'dada' }

 

 

更新 : 2017-10-19 

this.formControl.setValidators(null);
this.formControl.updateValueAndValidity();

reset validators 後記得調用重新驗證哦,Ng 不會幫你作的.

 

更新 : 2017-10-18 

formControl 的監聽與廣播 

兩種監聽方式 

1. control.valueChanges.subscribe(v)  
2. control.registerOnChange((value, emitViewToModelChange)
一般咱們是想監聽來自 view 的更新, 當 accessor.publishMethod(v) 的時候, 上面第一種會被廣播, 第二種則收不到. 因此想監聽 view -> model 使用第一種 
那麼若是咱們要監聽來自 control.setValue 的話, model -> view or just model change, 咱們使用第 2 種, 
setvalue 容許咱們廣播時聲明要不要 讓第一種和第二種觸發
emitEvent = false 第一種不觸發
emitModelToViewChange = false 第 2 種不觸發 
emitViewToModelChange = false 第 2 種觸發, 而後第二個參數是 就是 emitViewToModelChange 
對了,雖然兩種叫 changes 可是值同樣也是會觸發的,若是不想重複值觸發的話,本身寫過濾唄.
總結: 
在作 view accessor 時, 咱們監聽 formControl model to view 因此使用 registerOnChange
// view accessor 
this.viewValue = this.formControl.value; // first time
this.formControl.registerOnChange((v, isViewToModel) => { // model to view
  console.log('should be false', isViewToModel);
  this.viewValue = v;
});

而後經過 formControl view to model 更新

viewToModel(value: any) {
  this.formControl.setValue(value, {
    emitEvent: true,
    emitModelToViewChange: false,
    emitViewToModelChange: true
  });
}

而後呢在外部,咱們使用 valueChanges 監聽 view to model 的變化

this.formControl.valueChanges.subscribe(v => console.log('view to model', v)); // view to model

再而後呢, 使用 setValue model to view 

modelToView(value: any) {
  this.formControl.setValue(value, {
    emitEvent: false,
    emitModelToViewChange: true,
    emitViewToModelChange: false
  });
}

 最關鍵的是在作 view accessor 時, 不要依賴 valueChanges 應該只使用 registerOnChange, 這比如你實現 angular ControlvalueAccessor 的時候,咱們只依賴 writeValue 去修改 view.

對於 model to view 的時候是否容許 emitEvent 徹底能夠看你本身有沒有對其依賴,但 view accessor 確定是不依賴的,因此即便 emitEvent false, model to view 依然把 view 處理的很好纔對。

 

 

更新 : 2017-08-06 

formControlName and [formControl] 的注入

 <form [formGroup]="form">
  <div formGroupName="obj">
    <input formControlName="name" type="text">
    <input sURLTitle="name" formControlName="URLTitle" type="text">
  </div>
</form> 

<form [formGroup]="form">
  <div [formGroup]="form.get('obj')">
    <input [formControl]="form.get('obj.name')" type="text">
    <input [sURLTitle]="form.get('obj.name')" [formControl]="form.get('obj.URLTitle')" type="text">
  </div>
</form>

這 2 種寫法出來的結果是同樣的. 

若是咱們的指令是 sURLTitle

那麼在 sURLTitle 能夠經過注入獲取到 formControl & formGroup

@Directive({
  selector: '[sURLTitle]'
})
export class URLTitleDirective implements OnInit, OnDestroy {

  constructor(
    // 注意 : 不雅直接注入 FormGroupDirective | FormGroupName, 注入 ControlContainer 纔對.
    // @Optional() private formGroupDirective: FormGroupDirective,
    // @Optional() private formGroupName: FormGroupName,
    private closestControl: ControlContainer, // 經過抽象的 ControlContainer 能夠獲取到上一層 formGroup
    @Optional() private formControlDirective: FormControlDirective,
    @Optional() private FormControlName: FormControlName,
  ) { }

  @Input('sURLTitle')
  URLTitle: string | FormControl

  private sub: ISubscription
  ngOnInit() {
    let watchControl = (typeof (this.URLTitle) === 'string') ? this.closestControl.control.get(this.URLTitle) as FormControl : this.URLTitle;
    let sub = watchControl.valueChanges.subscribe(v => {
      (this.formControlDirective || this.FormControlName).control.setValue(s.toURLTitle(v));
    });
  }

  ngOnDestroy() {
    this.sub.unsubscribe();
  }
}

 

 

 

 

 

更新 : 2017-04-21 

form 是不能嵌套的, 可是 formGroup / formGroupDirective 能夠 

submit button 只對 <form> 有效果. 若是是 <div [formGroup] > 的話須要本身寫 trigger 

child form submit 並不會讓 parent form submit, 分的很開. 

 

 

更新 : 2017-03-22

小提示 : 

咱們最好把表單裏面的 button 都寫上 type.

由於 ng 會依據 type 來作處理. 好比 reset 

要注意的是, 若是你不寫 type, 默認是 type="submit".

<form [formGroup]="form" #formComponent >
    <button type="button" ></button>
    <button type="submit" ></button>
    <button type="reset" ></button>
</form>

另外, ng 把 formGroup 指令和 formGroup 對象區分的很明顯,咱們可不要搞混哦. 

上面 formComponent 是有 submitted 屬性的, form 則沒有 

formComponent.reset() 會把 submitted set to false, form.reset() 則不會. 

formComponent.reset() 會間接調用 form.reset(), 因此數據會清空.

<button type="reset"> 雖然方便不過不支持 window.confirm

咱們要本身實現 reset 的話,就必須使用 @Viewchild 來注入 formGroup 指令. 

 

 

2016-08-30

refer : 

 

ng2 的表單和 ng1 相似, 也是用 control 概念來作操做, 固然也有一些地方不一樣 

最大的特色是它把表單區分爲 template drive and model drive 

template drive 和 ng1 很像, 就是經過指令來建立表單的 control 來加以操做. 

model drive 則是直接在 component 內生成 control 而後再綁定到模板上去. 

template drive 的好處是寫得少,簡單, 適合用於簡單的表單

簡單的定義是 :

-沒有使用 FormArray,

-沒有 async valid,

-沒有 dynamic | condition validation  

-總之就是要很簡單很靜態就對了啦.

固然若是你打算本身寫各作複雜指令去讓 template drive 無所不能, 也是能夠辦到的. 有心鐵棒磨成針嘛.. 你愛磨就去啦..

model drive 的好處就是方便寫測試, 不須要依賴 view. 

 

模板驅動 (template drive):

<form novalidate #form="ngForm" (ngSubmit)="submit(form)">
       
</form>

沒能嵌套表單了哦! 

經過 #form="ngForm" 咱們能夠獲取到 ngForm 指令, 而且操做它, 好比 form.valid, form.value 等 

ngSubmit 配合 button type=submit 使用 

<input type="text" placeholder="name"
        [(ngModel)]="person.name" name="name" #name="ngModel" required minlength="5" maxlength="10" />
<p>name ok : {{ name.valid }}</p>  

[(ngModel)] 實現雙向綁定和 get set value for input 

name="name" 實現 create control to form 

#name 引用 ngModel 指令,能夠獲取 name.valid 等 

required, minlength, maxlength 是原生提供的驗證. ng2 給的原生驗證指令不多,連 email,number 都沒有哦. 

<fieldset ngModelGroup="address">
    <legend>Address</legend>
    <div>
        Street: <input type="text" [(ngModel)]="person.address.country" name="country" #country="ngModel" required />
    </div> 
    <div>country ok : {{ country.valid }}</div>
</fieldset>

若是值是對象的話,請開多一個 ngModelGroup, 這有點像表單嵌套了.

<div>
    <div *ngFor="let data of person.datas; let i=index;">
        <div ngModelGroup="{{ 'datas['+ i +'].data' }}">
            <input type="text" [(ngModel)]="data.key" name="key" #key="ngModel" required />
        </div>
    </div>
</div>  

遇到數組的話,建議不適用 template drive, 改用 model drive 比較適合. 上面這個有點牽強...

 

 

在自定義組件上使用 ngModel 

ng1 是經過 require ngModelControl 來實現 

ng2 有點不一樣 

@Component({ 
    selector: "my-input",
    template: `
        <input type="text" [(ngModel)]="value"  />
    `,
    providers: [{
        provide: NG_VALUE_ACCESSOR,
        useExisting: forwardRef(() => MyInputComponent),
        multi: true
    }]
})

首先寫一個 provide 擴展 NG_VALUE_ACCESSOR 讓 ng 認識它 .

export class MyInputComponent implements OnInit, ControlValueAccessor {}

實現 ControlValueAccessor 接口 

//outside to inside     
writeValue(outsideValue: any): void {
    this._value = outsideValue;
};

//inside to outside
//註冊一個方法, 當 inside value updated then need call it : fn(newValue)
registerOnChange(fn: (newValue : any) => void): void {
    this.publichValue = fn;
}

//inside to outside
registerOnTouched(fn: any): void {
    this.publichTouched = fn;
}  

主要 3 個方法 

writeValue 是當外部數據修改時被調用來更新內部的。 

registerOnChange(fn) 把這個 fn 註冊到內部方法上, 當內部值更新時調用它 this.publishValue(newValue); 

registerOnTouched(fn) 也是同樣註冊而後調用當 touched 

使用時這樣的 : 

<my-input [(ngModel)]="person.like" name="like" email #like="ngModel" ></my-input>
value : {{ like.value }}

執行的順序是 ngOnInit-> writeValue-> registerOnChange -> registerOnTouched -> ngAfterContentInit -> ngAfterViewInit

若是內部也是使用 formControl 來維護 value 的話, 一般在寫入時咱們能夠關掉 emitEvent, 否則又觸發 onChange 去 publish value (但即便你這樣作,也不會形成死循環 error 哦, ng 好厲害呢)

writeValue(value: any): void { 
    this.formControl.setValue(value,{ emitEvent : false });        
};

 

Model drive

自定義 validator 指令 

angular 只提供了 4 種 validation : required, minlength, maxlength, pattern

好吝嗇 ! 

class MyValidators {
    static email(value: string): ValidatorFn {
        return function (c: AbstractControl) {            
            return (c.value == value) ? null : { "email": false };            
        };
    }  
}

this.registerForm = this.formBuilder.group({
    firstname: ['', MyValidators.email("abc")] 
}); 

若是驗證經過返回 null, 若是失敗返回一個對象 { email : false }; 

還有 async 的,不過咱們有找到比較可靠的教程,之後纔講吧.

上面這個是 model drive 的,若是你但願支持 template drive 能夠參考這個 : 

http://blog.thoughtram.io/angular/2016/03/14/custom-validators-in-angular-2.html

 

在大部分狀況下, model drive 是更好的選擇, 由於它把邏輯纔開了, 不要依賴模板是 angular2 一個很重要的思想, 咱們要儘可能少依賴模板來寫業務邏輯, 由於在多設備開發狀況下模板是不能複用的.

並且不依賴模板也更容易測試. 

咱們看看整個 form 的核心是什麼 ? 

就是對一堆有結構的數據, 附上驗證邏輯, 而後綁定到各個組件上去與用戶互動. 

因此 model drive 的開發流程是 : 定義出有結構的數據 -> 綁定驗證 -> 綁定到組件 -> 用戶操做 (咱們監聽而且反應)

這就是有結構的數據 : 

export class AppComponent {
    constructor(private formBuilder: FormBuilder) { console.clear(); }
    registerForm: FormGroup;
    ngOnInit() {
        this.registerForm = this.formBuilder.group({
            firstname: ['', Validators.required],
            address: this.formBuilder.group({
                text : ['']
            }),
            array: this.formBuilder.array([this.formBuilder.group({
                abc : ['']
            })], Validators.required)
        }); 
    }
}

angular 提供了一個 control api, 讓咱們去建立數據結構, 對象, 數組, 嵌套等等. 

this.formBuilder.group 建立對象

this.formBuilder.array 建立數組 ( angular 還有添加刪除數組的 api 哦 )

firlstname : [ '', Validators.required, Validators.requiredAsync ] 這是一個簡單的驗證綁定, 若是要動態綁定的話也是經過 control api 

control api 還有不少種對數據, 結構, 驗證, 監聽的操做, 等實際開發以後我才補上吧. 

template drive 其實也是用同一個方式來實現的, 只是 template drive 是經過指令去建立了這些 control, 而且隱藏了起來, 因此其實看穿了也沒什麼, 咱們也能夠本身寫指令去讓 template drive 實現全部的功能.

接下來是綁定到 template 上.

<form [formGroup]="registerForm">
    <input type="text" formControlName="firstname"/> 
    <fieldset formGroupName="address"> 
        <input type="text" formControlName="text"> 
    </fieldset> 
    <div formArrayName="array">
            <div *ngFor="let obj of registerForm.controls.array.controls; let i=index">
            <fieldset [formGroupName]="i"> 
                <input type="text" formControlName="abc"> 
            </fieldset> 
            </div>
    </div>              
</form> 

值得注意的是 array 的綁定, 使用了 i 

特別附上這 2 篇 : 

https://scotch.io/tutorials/how-to-build-nested-model-driven-forms-in-angular-2

https://scotch.io/tutorials/how-to-deal-with-different-form-controls-in-angular-2

 

async validator 

static async(): AsyncValidatorFn { 
    let timer : NodeJS.Timer;  
    return (control: AbstractControl) => { 
        return new Promise((resolve, reject) => {
            clearTimeout(timer);
            timer = setTimeout(() => {
                console.log("value is " + control.value);
                console.log("ajaxing");
                let isOk = control.value == "keatkeat";
         //假設是一個 ajax 啦 setTimeout(()
=> { if (isOk) { return resolve(null); } else { resolve({ sync: true }); } }, 5000); }, 300); }); }; } this.form = this.formBuilder.group({ name: ["abcde", MyValidators.sync(), MyValidators.async()] });

angular 會一直調用 async valid 因此最好是寫一個 timer, 否則一直 ajax 很浪費.

 

 

經常使用的手動調用 : 

this.form.controls["name"].markAsPending(); //async valid 時會是 pending 狀態, 而後 setErrors 會自動把 pending set to false 哦
this.form.controls["name"].setErrors({ required : true }); 
this.form.controls["name"].setErrors(null); // null 表示 valid 了   
this.form.controls["name"].markAsTouched();
this.form.controls['name'].updateValueAndValidity(); //trigger 驗證 (好比作 confirmPassword match 的時候用到) 
this.form.controls['name'].root.get("age"); //獲取 sibling 屬性, 驗證的時候常常用到, 還支持 path 哦 .get("address.text")
this.form.controls["confirmPassword"].valueChanges.subscribe(v => v); //監放任何變化

這些方法都會按照邏輯去修改更多相關值, 好比 setErrors(null); errors = null 同時修改 valid = true, invalid = false; 

特別說一下 AbstractControl.get('path'),

-當 path 有包含 "." 時 (例如 address.text), ng 會把 address 當成對象而後獲取 address 的 text 屬性. 可是若是你有一個屬性名就叫 'address.text' : "value" 那麼算是你本身挖坑跳哦.  

-若是要拿 array 的話是 get('products.0') 而不是 get('products[0]') 哦.

 

更新 : 2016-12-23 

touch and dirty 的區別 

touch 表示被"動"過 ( 好比 input unblur 就算 touch 了 )

dirty 是說值曾經被修改過 ( 改了即便你改回去同一個值也時 dirty 了哦 )

 

更新 : 2017-02-16

概念 : 

當咱們本身寫 accessor 的時候, 咱們也應該 follow angular style 

好比自定義 upload file 的時候, 當 ajax upload 時, 咱們應該把 control 的 status set to "PENDING" 經過 control.markAsPending()

pending 的意思是用戶正在進行操做, 多是正在 upload or 正在作驗證. 總之必須經過 control 表達出去給 form 知道, form 則可能阻止 submitt 或則是其它特定處理. 

要在 accessor 裏調用 formContril 咱們須要注入

@Optional() @Host() @SkipSelf() parentControlContainer, 

配合 @Input formControlName 就能夠獲取到 formControl

最後提一點, 當 control invalid 時, control.value 並不會被更新爲 null. 我記得 angular1 會自動更新成 null. 這在 angular2 是不一樣的。 

 

modelToView( value: any) {
this. formControl. setValue( value, {
emitEvent: false,
emitModelToViewChange: true,
emitViewToModelChange: false
});
}
相關文章
相關標籤/搜索