Angular 2 ++ | NgForm:Form.Dirty总是很脏

时间:2017-09-05 17:56:44

标签: forms angular validation typescript dirty-tracking

确定NgForm是否完全之前任何用户输入

<小时/> 似乎form.dirty在更改后不会对其值进行编辑,form.touched似乎始终为false,无论如何:dirty为{{1} }},touchedtetched

template.html
touched
component.ts
<form #form="ngForm" (ngSubmit)="handleSubmission($event, {}, form)">
    ...
    <input
        #input
        type="text"
        [name]="item.title"
        [(ngModel)]="item.estimate"
        (ngModelChange)="handleEstimateChange(item, item.estimate, input, form)"
    />
    ...
</form>

在TypeScript中,我去抖动 export class LeComponent { @Input('data') public data: any; public handleEstimateChange: Function; constructor(private $: Sandbox) { this.handleEstimateChange = $.debounce(this.handleEstimate.bind(this), (1000*0.2)); } handleEstimate(item: any, estimate: number, input: HTMLInputElement, form: NgForm) { if (!estimate) delete item.esitmate; (this, item, estimate, input, form); // Why does form.dirty never change back to pristine again??? } } 处理程序,以便在我检查之前为Angular提供更改ngModelChange值的机会。这是因为form.dirtyngModelChange对象被修改之前被触发。

如果NgForm,因为!estimate,则将其重新设置为原始值estimate === ""。在这种情况下,表单应该完全,就像任何用户输入发生之前一样。

但是,当我在评论正上方的行上添加断点并将undefined输出到form.dirty时, NgForm永远不会将console更改回{{1 }}

是否可以确定表单是否与任何用户输入之前的完全一样?

显然,我可以编写自己的逻辑,但这并不意味着dirty有点无用吗?我不得不失去一些东西,对吧?怎么可能并不意味着

我已经看过其他一些SO问题 - 第一个问题类似,但绝对不是我要问的问题。他们在问这是故意 - 我不在乎;我想知道如何实现上述目标。

关闭,但没有雪茄:

angular2 formcontrol stays dirty even if set to original value

Block routing if form is dirty [ Angular 2 ]

Angular 2 getting only the dirty values in a controlgroup

How do I programmatically set an Angular 2 form control to dirty?

Angular 2.x/4.x & bootstrap: patchValue does not alter dirty flag. Possible bug?

2 个答案:

答案 0 :(得分:1)

使用模板驱动的表单和非常扁平的数据模型,我实现了这样:

private currentProduct: IProduct;
private originalProduct: IProduct;

get isDirty(): boolean {
    return JSON.stringify(this.originalProduct) !== JSON.stringify(this.currentProduct);
}

get product(): IProduct {
    return this.currentProduct;
}
set product(value: IProduct) {
    this.currentProduct = value;
    // Clone the object to retain a copy
    this.originalProduct = Object.assign({}, value);
}

但这仅适用于非常简单的情况。

正如我在评论中所提到的,使用被动表单可以更灵活地管理与用户条目分开的数据模型。

答案 1 :(得分:0)

什么是最有用的

template.html
<form #form="ngForm" (ngSubmit)="handleSubmission($event, {}, form)">
    ...
    <input
        #input
        type="text"
        [name]="item.title"
        [attr.name]="item.title"
        [(ngModel)]="item.estimate"
        (ngModelChange)="handleEstimateChange(item, item.estimate, input, form)"
    />
    ...
</form>
component.ts
export class LeComponent {
    @Input('data') public section: any;
    public handleEstimateChange: Function;

    private resetFormControl = (input: HTMLInputElement, form: NgForm) => {
        var name = input.name, control = form.controls[name];
        control.reset();
        // control.markAsPristine();
        // control.setValue(undefined);
        // control.updateValueAndValidity();
    };

    constructor(private $: Sandbox) {
        this.handleEstimateChange = $.debounce(this.handleEstimate.bind(this), (1000*0.2));
    }

    handleEstimate(item: any, estimate: number, input: HTMLInputElement, form: NgForm) {
        if (!estimate) this.resetFormControl(input, form);
        (this, item, estimate, input, form);
        // Why does form.dirty never change back to pristine again???
    }

}
  

注意

     
      
  • [attr.name]="..."(template.html)
  •   
  • resetFormControl
  •   

基本上,仅仅delete值是不够的,因为它仍然存在于FormControl对象(form.controls)上。要正确清除它,请为单个控件调用control.reset() - 然后调用.markAsPristine()与父NgForm进行通信。此外,input.name为空,因为它仅由ng-reflect-name表示,除非[attr.name]阐明相同的值 - [name]实际上只是因为它是Angular所需的。

现在,只要<input />值发生变化 - 就会失败 - 我们重置输入,确保如果 all 都是假的,Angular会自动处理正确地NgForm的脏状态。