Angular 6:如何使用索引插值为动态反应形式添加验证?

Angular 6: How to add validation to dynamic reactive form with index interpolation?

我正在尝试创建一个经过适当验证的动态反应表单。

基于业务逻辑,我们需要根据数据填充输入字段。我创建了一个变量调用 formErrors 并在字段无效时动态添加错误消息。我试图为错误添加 *NgIf[hidden] 指令。但是,这是不允许的。 (以下跨度语法无效)

我可能有一个包含相关错误的 FormControl 列表(例如 wage_0、wage_1、wage_2、...)。如何将错误消息推送到 html 模板?最佳做法是什么?

组件html

<form *ngIf="cuList" [formGroup]="reportForm" role="form">
    <p-accordionTab *ngFor='let cu of cuList; let counter = index'>
        <div>
            <div class="input-group">
                <input class="form-control"
                    name="wages"
                    placeholder=""
                    formControlName="wages_{{ counter }}"  <!-- dynamically name the formControl -->
                    currencyMask
                    [(ngModel)]="cu.wage"
                    [options]="{ prefix: '$ ', thousands: ',', allowNegative: false, precision: 0}"
                    maxlength="15"
                    required />
                <div class="input-group-append">
                    <span class="input-group-text">.00</span>
                </div>
            </div>
            <span [hidden]="formErrors.wages_{{counter}}"></span>   <!-- show error message -->
            <!-- or -->
            <span *ngIf="formErrors.wages_{{counter}}"></span>
        </div>
    </p-accordionTab>
</form>       

组件 ts:

export class EmployerCuListComponent implements OnInit {
    private _accordion: Accordion;

    @ViewChild('accordion') set content(content: Accordion) {
        this._accordion = content;
    }

    reportForm: FormGroup;
    formErrors = {};
    cuList: EmployerCu[];

    constructor(private _fb: FormBuilder) {}

    ngOnInit() {
        this._employercuService.getEmployerCu().subscribe(data => {
            this.cuList = data;
            if (this.cuList) {
                this.createForm(this.cuList);
            }
        });
    }

    createForm(cuList: EmployerCu[]) {
        const group = {};

        cuList.forEach((cu, index) => {
            group['wages_' + index] = ['', [Validators.required]];
            this.formErrors['wages_' + index] = '';
        });
        this.reportForm = this._fb.group(group);
    }
}

请帮忙!提前致谢!

我想出了另一个模板驱动表单的解决方案。我认为这对我们的动态案例来说是最好的。它允许通过适当的验证动态创建表单。

组件HTML

<p-accordion #accordion [hidden]="!cuList" [multiple]="true">
    <p-accordionTab *ngFor='let cu of cuList; let counter = index'>
        <form #form="ngForm" (ngSubmit)="form.form.valid" role="form" novalidate>  <!-- create sub-form -->
            <div class="row form-group col-md-12 pr-0">
                <div class="col-md-4 pl-0 ml-0 mt-3 pr-0" [ngClass]="{ 'has-error': wages.invalid && (wages.dirty || wages.touched || form.submitted) }">
                    <div class="input-group">
                        <input class="form-control"
                               name="wages"
                               placeholder=""
                               #wages="ngModel"        <!-- assign template variable -->
                               ngControl="wages"
                               currencyMask
                               [(ngModel)]="cu.wage"
                               [options]="{ prefix: '$ ', thousands: ',', allowNegative: false, precision: 0}"
                               maxlength="15"
                               required />
                        <div class="input-group-append">
                            <span class="input-group-text">.00</span>
                        </div>
                    </div>
                    <span *ngIf="wages.invalid && (wages.dirty || wages.touched || form.submitted)">Field cannot be blank. Please enter an amount.</span>
                </div>
            <button *ngIf="counter !== cuList.length-1" type="submit" class="btn btn-primary btn-normal float-right" (click)="openNext(cu)">Next</button>
        </form>
    </p-accordionTab>
</p-accordion>

组件 ts

export class EmployerCuListComponent implements OnInit {
    @ViewChild('accordion') accordion: Accordion;
    @ViewChildren('form') cuForms: QueryList<NgForm>;

    constructor(private _employercuService: EmployerCuService) {}

    ngOnInit() {
        this._employercuService.getEmployerCu().subscribe(data => {
            this.cuList = data;
        });
    }

    formHasError() {
        this.cuForms.some((cuForm, index) => {
            if (cuForm.form.invalid) {
                cuForm.form.controls['wages'].markAsTouched();
                cuForm.form.controls['payments'].markAsTouched();
                cuForm.form.controls['excessPayroll'].markAsTouched();
                return true;
            }
        });
        return false;
    }
}

不确定这是否是最佳做法。但它解决了我的问题。我在 HTML 模板中推送表单创建并使用 @ViewChidren 获取表单数组并集中控制并充分利用 NgForm 在 component.ts.

中提供的属性和方法

如果您有更好的主意,请告诉我。谢谢!