角度6:如何通过索引插值向动态反应形式添加验证?

时间:2018-08-08 23:30:06

标签: angular typescript angular6 angular-reactive-forms

我正在尝试创建具有适当验证的动态反应形式。

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

我可能有一个带有相关错误的FormControl列表(例如,工资_0,工资_1,工资_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);
    }
}

请帮助!预先感谢!

1 个答案:

答案 0 :(得分:0)

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

组件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中提供的属性和方法。

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