【问题标题】:Angular 2++ | NgForm: Form.Dirty is Always Dirty角 2++ | NgForm:Form.Dirty 总是脏的
【发布时间】:2017-09-05 17:56:43
【问题描述】:

确定 NgForm 是否与 任何用户输入之前的 完全一样


似乎form.dirty 在更改后不会对其值进行编辑,而form.touched 似乎总是false,无论如何:dirtytouchedtouchedtetched。 模板.html
<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>
组件.ts
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???
    }

}

在 TypeScript 中,我正在去抖动 ngModelChange 处理程序,以便 Angular 在我检查之前有机会更改 form.dirty 值。这是因为ngModelChangeNgForm 对象被修改之前被触发。

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

但是,当我在评论正上方的行上放置一个断点并将form.dirty 输出到console 时,NgForm 永远不会将dirty 更改回false

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

显然,我可以编写自己的 dirty 逻辑,但这是否意味着 NgForm 有点没用?一定有什么我想念的,对吧? 怎么可能不代表

我查看了其他一些 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?

【问题讨论】:

  • 澄清示例:如果表单以输入值“something”开始,然后用户将其编辑为“something else”,然后点击撤消(例如)将值恢复为“某物”,您是否希望脏在输入更改时变为真,然后在值恢复为原始值时变为假?
  • 正如引用的其他网站所说,“脏”意味着已编辑……即使您将其编辑回相同的值。 “脏”处理跟踪表单的原始值,因此它不知道用户是否放回相同的值。 Angular 有 no 内置机制来保持原始数据的状态。如果您需要该功能,您需要自己实现它......或使用类似的东西:github.com/ngrx/store
  • 另一种选择是使用响应式表单而不是模板驱动的表单。那么您的数据模型不会被用户所做的任何更改所更改。然后,您可以将表单值与原始数据模型进行比较,以确定表单看起来是否与编辑前完全一样。
  • @ConorMancone,感谢您的询问。这正是目标。
    @DeborahK,我知道 Angular 对 dirty 的含义有不同的概念,我碰巧不同意说 edited 实际上是 touched 。我也将避免使用 Reactive Forms,因为 Google Avenue 上说它们将被弃用 - 但感谢您的建议。
  • @Cody 你有参考/链接吗?我在 Angular 文档团队中,还没有听说过关于 Reactive Forms 的任何消息。

标签: forms angular validation typescript dirty-tracking


【解决方案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);
}

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

正如我在 cmets 中提到的,使用响应式表单可以让您更灵活地管理与用户条目分开的数据模型。

【讨论】:

    【解决方案2】:

    什么是最有用的


    模板.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>
    
    组件.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

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

    现在,只要 &lt;input /&gt; 值发生变化——并且它是假的——我们重置输入以确保如果 all 都是假的,Angular 将自动处理 @ 987654336@ 的脏状态正确。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-23
      • 1970-01-01
      • 2023-03-08
      • 2011-02-21
      • 1970-01-01
      • 2012-11-10
      • 2021-12-31
      相关资源
      最近更新 更多