我在Angular 2.1中有一个模板驱动的表单,其中包含许多标准控件(<input>, <select>
等)和一个自定义控件,它本身包含多个输入元素。
我已在自定义控件上实现了ControlValueAccessor,并且它正确地将其更改/触摸/有效值传播到父窗体。
但是..在父窗体上我有一个保存按钮,保存后我想要清除脏/触摸状态(因为这会影响应用的css),如下所示:
save(myForm: NgForm) {
myForm.form.markAsPristine();
myForm.form.markAsUntouched();
}
这适用于顶级父表单中的所有元素和自定义控件本身但自定义控件中的<input>
字段仍标记为已触摸/脏(并且这接受预先保存的造型。)
是否有一种方法可以在更改脏/触摸状态时通知自定义控件,以便它可以清除它的子<input>
元素以匹配?似乎如果<input>
元素在自定义控件中,则不会通过调用父表单上的markAsPristine / Untouched来更新它们。
谢谢!
答案 0 :(得分:10)
使用活动标志的解决方法可以完成这项工作,但我也找到了另一种方法。
在父窗体上,我可以将自定义子组件作为ViewChild访问。
,即在父母表格中:
@ViewChild(CustomChildComponent) child1: CustomChildComponent;
然后,当我保存在父表格中时,直接打电话给那个孩子。
save(myForm:NgForm){
// clear anything at the parent form level
myForm.form.markAsPristine();
myForm.form.markAsUntouched();
// tell the custom component to do the same
this.child1.markAsPristineAndUntouched();
}
我定义的CustomChildComponent中的位置 ..
// get the input controls in the the child that we want to clear
@ViewChild('surname') surnameField: NgModel;
markAsPristineAndUntouched() {
this.surnameField.control.markAsPristine();
this.surnameField.control.markAsUntouched();
// .. clear other controls ..
}
答案 1 :(得分:8)
尝试像这样添加controls['nameOfControl']
myForm.form.controls['nameOfControl'].markAsPristine();
上面的代码仅适用于表单控件。
以下似乎是一个很好的解决方法:
active = true;
newModel() {
this.model = new yourModel(2, '',true, '');
this.active = false;
setTimeout(() => this.active = true, 0);
}
使用新模型重置表单并恢复'pristine'类状态。 通过切换'active'标志将导致通过NgIf删除/重新添加表单。是的,这是一个小工作,直到他们可以修复:)
希望有所帮助
答案 2 :(得分:0)
markAsPristine()
可以影响控件本身,或标记所有直接祖先控件...
就我而言,我想将所有后代控件标记为原始/未更改。 我可以使用FormGroup.reset()
来完成; reset()
可以影响后代:
重置FormGroup,将所有后代标记为原始且未更改,并将所有后代的值设置为空。
因此,使用OP的代码,我可以使用它已经具有的值来重置表单:
myForm.form.reset(myForm.form.getRawValue(), {emitEvent: false})
我尽量避免副作用。
getRawValue()
而不是value
来获取禁用控件的值。 emitEvent
;这意味着没有valueChanges将被触发。答案 3 :(得分:0)
我的解决方案是观察主机变化。
我有一个实现 controlValueAccesor 接口的组件。我把这个组件用成一个表单,用ngModel。
当 Angular 表单 api 更改宿主元素类属性时,将其设置为dirty、prinstine、touched 等...我将 mi 组件类属性设置为宿主类属性。
构造函数(私有主机元素:ElementRef){
this.changes = new MutationObserver((mutations: MutationRecord[]) => {
mutations.forEach(
(mutation: MutationRecord) => (this.controlClasses = mutation.target['className']),
);
});
this.changes.observe(this.hostElement.nativeElement, {
attributes: true,
attributeFilter: ['class'],
});
}
在模板上
<span class="ui-float-label">
<input
#inputElement
[disabled]="disabled"
[type]="type"
[required]="required"
[(ngModel)]="value"
(ngModelChange)="handleValueChange($event)"
(blur)="onBlur()"
[pattern]="pattern"
[type]="type"
[size]="size"
pInputText
class="p-inputtext"
[ngClass]="controlClasses"
/>
<label *ngIf="!required" for="float-input">{{ placeholder }}</label>
<label *ngIf="required" for="float-input">{{ placeholder }}*</label>
</span>
现在每次主机更改他的类时,更改都会传播到子控件。