【问题标题】:Detect which FormControl in FormArray validator caused value change检测 FormArray 验证器中的哪个 FormControl 导致值更改
【发布时间】:2018-01-25 19:29:20
【问题描述】:

我可以轻松验证数组是否完全满足某些验证规则。当我想与表单数组中的特定控件进行交互时,问题就出现了。

我有包含表单组的表单数组。每个表单组都有几个表单控件。

组如下所示:

const rowGroup = new FormGroup({
    'range': new FormControl(row.range, [Validators.required, CustomValidators.range([1, 10000])]),
    'multifamily': new FormControl(row.multifamily, [Validators.required, Validators.min(0), CustomValidators.range([0, 10000])]),
    'office': new FormControl(row.office, [Validators.required, Validators.min(0), CustomValidators.range([0, 10000])]),
    'retail': new FormControl(row.retail, [Validators.required, Validators.min(0), CustomValidators.range([0, 10000])]),
    'other': new FormControl(row.other, [Validators.required, Validators.min(0), CustomValidators.range([0, 10000])])
});

表单数组包含组和进行验证的ascendingValidation 函数。组是动态添加的,并且不受限制。

const array = new FormArray([rowGroup], ascendingValidation);

在页面结果将是网格:

表单需要对“LTV 范围顶部 (%)”列执行升序验证。

示例(我总是在谈论“LTV 范围顶部 (%)”列):

  1. 第一种情况:如果用户将第一行中的值更改为 44 而不是 41,则此字段(表单控件)将无效,因为用户破坏了升序。我只想在第一行显示错误消息,因为用户更改了该值。
  2. 第二种情况:如果用户更改第二行并添加 40 而不是 43,则该字段需要无效。我只想在第二行字段错误消息中显示。
  3. 第三种情况:如果用户用户在第一行添加 45 而不是 41,则需要在该字段上显示错误消息。如果用户在第二行添加 46 而不是 43,则需要在第一行删除错误,因为满足升序。

问题:

我正在使用表单数组级别的验证。 我的问题不是如何实现算法来检查数组升序以及哪些值不是升序。这是最简单的部分

在表单数组验证中,当值发生更改时,我可以访问所有数组元素。实际上我不知道哪个控件是最新更改的。

如何检测是哪个控件导致表单数组验证器的值变化?

有没有更好的方法来进行这种验证?

【问题讨论】:

  • 如果您将这个问题分成两个单独的问题(现在有点宽泛)并包含相关代码,包括您尝试过但没有奏效的内容,这可能对其他人有所帮助。
  • 有网格编辑器模板吗?网格提供了一个索引范围的变量或者你可以使用 ngFor 指令的索引吗?
  • @LeonardoNeninger 网格由ngFor 生成。问题是如何检测发出值变化的控件?
  • @Z.Bagley 谢谢。你有建议我如何拆分吗?一般来说,我的问题是如何检测表单数组验证器中哪个控件发出值变化,这是正确的方法吗?
  • 我会把关于网格的所有内容放在另一个问题中(如果下面的答案不能解决问题,可能会删除并重新询问这个问题)。此外,对于您的inputs,您可以添加一个(change)="checkChange($event)",这将为您提供$event.target 并检测个别更改。使用ViewChild 是检测更改的另一种选择,但总体思路保持不变。希望这会有所帮助!

标签: angular reactive-forms


【解决方案1】:

这是另一种可以帮助您的方法... 我使用 ngx-datatable,它为列模板提供了一个完整的 api。下面的逻辑跟踪上次更改的控件名称和行索引。

我的表定义是

<ngx-datatable id="tblMain" #tblMain formGroupName="details" class="material" *ngIf="!hideTable"
                       [rows]="items"
                       [headerHeight]="50"
                       [footerHeight]="50"
                       [rowHeight]="'auto'"
                       [columnMode]="'force'"
                       [trackByProp]="'id'"
                       [rowClass]="getRowClass"
                       >

注意 formGroupName="details" 是一个嵌套的 FormArray

我的专栏模板是这个。

<ng-template let-row="row" let-rowIndex="rowIndex" let-value="value" ngx-datatable-cell-template>...</ng-template>

在模板中我可以控制部分我显示视图或编辑部分..

<!--View-->
<div *ngIf="row != currentEditingDetail">...</div>

<!--Edit-->
<div *ngIf="row == currentEditingDetail" [formGroupName]="rowIndex">...</div>

注意表单组名,正在编辑的行的索引

在编辑部分中,我显示了一个具有 keydown 事件的输入元素

<input type="hidden" formControlName="productValue"  [(ngModel)]="row.productId" (keydown)="processInputKeyDown($event, rowIndex, 'product')"/>

注意:您可以使用 processInputKeyDown 来跟踪上次更改的元素。

  Component({})
  export class ComponentComponent
{
  ...
  processInputKeyDown = (event, index, control) =>{this.lastGroup = i; this.lastControl = control}
  ...
}

希望对你有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-20
    • 1970-01-01
    • 2020-05-24
    • 2017-06-09
    • 1970-01-01
    • 2018-11-21
    • 2019-08-01
    • 1970-01-01
    相关资源
    最近更新 更多