2017-04-21 4 views
11
과 같이 각도 (4.x의) 나는 ReactiveForms을 사용하고 난 내 FormControl ("입력")에 valueChanges에 가입했습니다와

:ValueChanges도 emitEvent와 때 Form.enable을 트리거 : 거짓

export class App { 
    version:string; 
    formControl = new FormControl('default', []); 
    form = this.fb.group({ 
     input: this.formControl, 
     input2: ('',[]) 
    }); 

    constructor(private fb: FormBuilder) { 
    this.version = `Angular v${VERSION.full}` 
    } 

    ngOnInit() { 
    this.formControl.valueChanges.subscribe(value => doSomething(value)); 
    } 

이제 FormControl 값의 변화에 ​​반응 할 수 있지만, 물론 어딘가에있는 양식의 값을 채우기 때문에 form.patchValue(data)을 사용하면됩니다.

이것은 사용자 변경이 아니기 때문에 이에 대응하고 싶지 않으므로 과 같은 플래그 (this.form.patchValue(data, {emitEvent: false}))를 추가하십시오.

예상대로 작동합니다.

는 지금은 형태가 로딩 될 때, 나는 장애인에 대한 모든 형태 this.form.disable({ emitEvent: false })을 설정하고, 로딩이 완료되면 다시 활성화로 전체 양식을 설정하는 몇 가지 논리를 가지고 : this.form.disable({ emitEvent: false })

그러나 나는 또한 논리가 그 다른 플래그에 따라서에 FormControl을 설정 활성화/비활성화 : Form는, 상태가 변경 될 때 this.formControl.enable({emitEvent: false});


, 그것은이 0을 유발 지금 볼 수있어 문제가된다, 비록 내가 emitEvent: false 플래그를 제공하더라도.

이것은 예상되는 동작입니까, 아니면 버그입니까? 플래그를 제공 할 때 이벤트가 전혀 트리거되지 않을 것으로 예상 했습니까? https://plnkr.co/edit/RgyDItYtEfzlLVB6P5f3?p=preview

+1

이이 버그가 실제로 것 같다 : https://github.com/angular/angular/issues/12366 – Bulan

+0

동일한 출처에 따라 수정 사항이 적용되고 github 문제가 종료됩니다. – Pac0

답변

7

모두 disable()enable() 기능 (code source) :

this._updateAncestors(!!opts.onlySelf); 

:

/** 
* Disables the control. This means the control will be exempt from validation checks and 
* excluded from the aggregate value of any parent. Its status is `DISABLED`. 
* 
* If the control has children, all children will be disabled to maintain the model. 
* @param {?=} opts 
* @return {?} 
*/ 
AbstractControl.prototype.disable = function (opts) { 
    if (opts === void 0) { opts = {}; } 
    this._status = DISABLED; 
    this._errors = null; 
    this._forEachChild(function (control) { control.disable({ onlySelf: true }); }); 
    this._updateValue(); 
    if (opts.emitEvent !== false) { 
     this._valueChanges.emit(this._value); 
     this._statusChanges.emit(this._status); 
    } 
    this._updateAncestors(!!opts.onlySelf); 
    this._onDisabledChange.forEach(function (changeFn) { return changeFn(true); }); 
}; 
/** 
* Enables the control. This means the control will be included in validation checks and 
* the aggregate value of its parent. Its status is re-calculated based on its value and 
* its validators. 
* 
* If the control has children, all children will be enabled. 
* @param {?=} opts 
* @return {?} 
*/ 
AbstractControl.prototype.enable = function (opts) { 
    if (opts === void 0) { opts = {}; } 
    this._status = VALID; 
    this._forEachChild(function (control) { control.enable({ onlySelf: true }); }); 
    this.updateValueAndValidity({ onlySelf: true, emitEvent: opts.emitEvent }); 
    this._updateAncestors(!!opts.onlySelf); 
    this._onDisabledChange.forEach(function (changeFn) { return changeFn(false); }); 
}; 

가 전화 한

나는이 여기에 테스트 할 수있는 쿵하는 소리를했습니다 부모의 updateValueAndValidity() 기능을 0123없이 호출하는 다음이 형태의 valueChanges 터를 트리거하고 콘솔에서 볼

this._valueChanges.emit(this._value); 

호출 69,플래그 :

Form.valueChanges: Object { input2: null } 

이는 형태가 아닌 default 입력 필드 컨트롤러에 의해 트리거됩니다. 조상 업데이트를 중지하려면 추가 플래그 -onlySelf: true을 제공하면됩니다.이 플래그는 조상이 아닌 자체 업데이트 만 알려줍니다. 그래서, 업데이트하지 않으려는 disable() 또는 enable() 함수를 호출 할 때마다 조상이 플래그 추가 :이 잎 formControls (자녀가없는 컨트롤)에 대한 문제를 해결할 수

disable(){ 
    this.form.disable({ 
    onlySelf: true, 
    emitEvent: false 
    }); 
} 

disableWEvent(){ 
    this.form.disable({ 
    onlySelf: true 
    }); 
} 

enable(){ 
    this.form.enable({ 
    onlySelf: true, 
    emitEvent: false 
    }); 
} 

enableWEvent(){ 
    this.form.enable({ 
    onlySelf: true 
    }); 
} 

disableCtrl(){ 
    this.formControl.disable({ 
    onlySelf: true, 
    emitEvent: false 
    }); 
} 

disableCtrlWEvent(){ 
    this.formControl.disable({ 
    onlySelf: true 
    }); 
} 

enableCtrl(){ 
    this.formControl.enable({ 
    onlySelf: true, 
    emitEvent: false 
    }); 
} 

enableCtrlWEvent(){ 
    this.formControl.enable({ 
    onlySelf: true 
    }); 
} 

하지만이 줄을

this._forEachChild(function (control) { control.disable({ onlySelf: true }); }); 

emitEvent: false없이 disable (또는 enable) 함수를 호출합니다. 이것은 앵귤러 버그처럼 보이므로 해결 방법으로이 두 기능을 무시할 수 있습니다. 먼저 수입 AbstractControl :

import {ReactiveFormsModule, FormBuilder, FormControl, Validators, AbstractControl} from '@angular/forms' 

두 기능을 오버라이드 (override)보다 :

// OVERRIDE disable and enable methods 
// https://github.com/angular/angular/issues/12366 
// https://github.com/angular/angular/blob/c59c390cdcd825cca67a422bc8738f7cd9ad42c5/packages/forms/src/model.ts#L318 
AbstractControl.prototype.disable = function (opts) { 
    if (opts === void 0) { opts = {}; } 
    this._status = 'DISABLED'; 
    this._errors = null; 
    this._forEachChild(function (control) { 
    control.disable(Object.assign(opts, {onlySelf: true})); 
    }); 
    this._updateValue(); 
    if (opts.emitEvent !== false) { 
     this._valueChanges.emit(this._value); 
     this._statusChanges.emit(this._status); 
    } 
    this._updateAncestors(!!opts.onlySelf); 
    this._onDisabledChange.forEach(function (changeFn) { return changeFn(true); }); 
}; 
AbstractControl.prototype.enable = function (opts) { 
    if (opts === void 0) { opts = {}; } 
    this._status = 'VALID'; 
    this._forEachChild(function (control) { 
    control.enable(Object.assign(opts, {onlySelf: true})); 
    }); 
    this.updateValueAndValidity({ onlySelf: true, emitEvent: opts.emitEvent }); 
    this._updateAncestors(!!opts.onlySelf); 
    this._onDisabledChange.forEach(function (changeFn) { return changeFn(false); }); 
}; 

업데이트 plunker : https://plnkr.co/edit/IIaByz4GlBREj2X9EKvx?p=preview

+0

광범위하고 좋은 답변, 좋은 파고, 감사합니다! 버그가 남아있는 한 해결 방법이므로 답변으로 표시하십시오. – Bulan