Angular(4.x)を使用して、ReactiveFormsを使用し、次のようにFormControl( "input")でvalueChangesにサブスクライブしました。
_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})
のようにフラグ_emitEvent: false
_を追加します。
期待どおりに動作します。
これで、フォームのロード時にフォーム全体を無効に設定するロジックがあり、this.form.disable({ emitEvent: false })
です。ロードが完了すると、フォーム全体が再び有効に設定されます:this.form.disable({ emitEvent: false })
ただし、さまざまなフラグに応じてFormControlを有効/無効に設定するロジックもあります:this.formControl.enable( {emitEvent: false});
私が今見ている問題は、Form
がステータスを変更すると、_FormControl.valueChanges
_、_emitEvent: false
_フラグを指定しても.
これは予想される動作ですか、それともバグですか?フラグを提供するときにイベントがまったくトリガーされないことを期待しましたか?
これをここでテストできるプランを作りました: https://plnkr.co/edit/RgyDItYtEfzlLVB6P5f3?p=preview
disable()
とenable()
の両方の関数( コードソース ):
_/**
* 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); });
};
_
に電話する:
_this._updateAncestors(!!opts.onlySelf);
_
親のupdateValueAndValidity()
関数をemitEvent
フラグなしで呼び出し、次に呼び出します
_this._valueChanges.emit(this._value);
_
これにより、フォームのvalueChanges
エミッターがトリガーされ、コンソールに表示されます。
_Form.valueChanges: Object { input2: null }
_
これは、default
入力フィールドコントローラーではなく、フォームによってトリガーされます。祖先の更新を停止するには、追加フラグ-_onlySelf: true
_を指定する必要があります。これは、祖先ではなく、自分だけを更新するように指示します。したがって、祖先を更新したくないdisable()
またはenable()
関数の各呼び出しで、このフラグを追加します。
_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
});
}
_
これはリーフformControls(子のないコントロール)の問題を解決しますが、この行
_this._forEachChild(function (control) { control.disable({ onlySelf: true }); });
_
_emitEvent: false
_を渡さずにdisable
(またはenable
)関数を呼び出します。 angularバグのように見えるので、回避策として、これら2つの関数をオーバーライドできます。最初にAbstractControl
をインポートします。
_import {ReactiveFormsModule, FormBuilder, FormControl, Validators, AbstractControl} from '@angular/forms'
_
両方の関数をオーバーライドする:
_// 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); });
};
_
更新されたプランカー: https://plnkr.co/edit/IIaByz4GlBREj2X9EKvx?p=preview