如果 FormArray 在响应式表单中为空或未定义,则不显示它

Don't show FormArray if it is empty or undefined in a Reactive Form

我刚开始学习 Angular 4 做我的第一个项目。

我创建了一个响应式表单来显示具有以下结构的表单:

Form (FormGroup)
  |
  --> aggLevels (FormArray)
       |
       --> aggregationLevelName (FormControl? I show it in a label)
       |
       --> variableDataForLevel (FormArray)
            |
            --> variableDataId (FormControl)
            |
            --> value (FormControl)

这是组件 HTML:

<form [formGroup]="varDataForm" (ngSubmit)="onSubmit()" novalidate>
    <div formArrayName="aggLevels"
         *ngFor="let agLevel of varDataForm.get('aggLevels')?.controls; let aggLevelId = index;">
        <div [formGroupName]="aggLevelId">
            <label>{{agLevel?.get('aggregationLevelName')?.value}}</label>
            <div formArrayName="variableDataForLevel"
                 *ngFor="let vardata of varDataForm.get('aggLevels')?.controls[0]?.get('variableDataForLevel')?.controls; let rowIndex = index;">
                <div [formGroupName]="rowIndex">
                    <select formControlName="variableDataId">
                        <option *ngFor="let gs1 of gs1AIs" [value]="gs1.Id">{{gs1.description}}</option>
                    </select>
                    <input formControlName="value" placeholder="Valor">
                    <div class="error" *ngIf="vardata.get('value').hasError('required') && vardata.get('value').touched">
                        Obligatorio
                    </div>
                </div>
            </div>
        </div>
    </div>
</form>

我的问题是 variableDataForLevel FormArray 中没有任何元素。我收到此消息:

ng:///AppModuleShared/VarDataComponent.ngfactory.js:49 ERROR Error: Cannot find control with path: 'aggLevels -> 1 -> variableDataForLevel -> 0'

我尝试在所有元素的末尾添加安全导航运算符?

varDataForm.get('aggLevels')?.controls[0]?.get('variableDataForLevel')?.controls

但我还是遇到了问题。 FormArray aggLevelsvariableDataForLevel 不是未定义的,因为当我创建它时我实例化了它。

如果 FormArray 为空,我该怎么做才能不显示它?

我是 Angular 的新手,我对如何修复它知之甚少。

这是该组件的组件打字稿 class:

import { Component, Inject } from '@angular/core';
import { FormBuilder, FormGroup, FormArray, FormControl, Validators } from '@angular/forms';
import { Http, RequestOptions, Headers } from '@angular/http';
import { IProductionOrder } from '../../interfaces/productionorder.interface';
import { IAggLevel } from '../../interfaces/aglevel.interface';
import { IGS1 } from '../../interfaces/gs1.interface';
import { IVarData } from '../../interfaces/vardata.interface';

@Component({
    selector: 'vardata',
    templateUrl: './vardata.component.html'
})

export class VarDataComponent {
    public productionorders: IProductionOrder[];
    public gs1AIs: IGS1[];

    public varDataForm: FormGroup = new FormGroup({});
    public selectedProductionOrder: string;

    constructor(private http: Http,
        @Inject('BASE_URL') private baseUrl: string,
        @Inject(FormBuilder) private fb: FormBuilder) {

        this.selectedProductionOrder = '';

        http.get(baseUrl + 'api/ProductionOrder/0').subscribe(result => {
            this.productionorders = result.json() as IProductionOrder[];

            console.log(this.productionorders);
        }, error => console.error(error));
    }

    productionOrderChanges() {
        if (this.selectedProductionOrder != '') {
            let urlVarData: string = this.baseUrl + 'api/VariableData/' + this.selectedProductionOrder;
            let urlAggLevel: string = this.baseUrl + 'api/AggregationLevelConfiguration/' + this.selectedProductionOrder;

            this.http.get(urlAggLevel).subscribe(result => {
                let aggLevels: IAggLevel[] = result.json() as IAggLevel[];

                console.log('niveles');
                console.log(aggLevels);

                if ((aggLevels != null) && (aggLevels.length > 0)) {

                    this.http.get(urlVarData).subscribe(result => {
                        let varDatas: IVarData[] = result.json() as IVarData[];

                        console.log('variable data');
                        console.log(varDatas);

                        this.varDataForm = this.fb.group({
                            aggLevels: this.fb.array(this.createForm(aggLevels, varDatas))
                        });

                    }, error => console.error(error));
                }

            }, error => console.error(error));
        }
        else
            this.varDataForm = new FormGroup({});
    }

    createForm(aggLevels: IAggLevel[], varDatas: IVarData[]): any[] {
        let array: any[] = [];

        for (let level of aggLevels) {
            let group: FormGroup;
            let varDataForLevel: IVarData[] =
                varDatas.filter(v => v.aggregationLevelConfigurationId == level.aggregationLevelConfigurationId);

            group = this.createFormGroupForLevel(level, varDataForLevel);
            array.push(group);
        }

        return array;
    }

    createFormGroupForLevel(level: IAggLevel, varDatas: IVarData[]): FormGroup {
        let group: FormGroup;

        group = this.fb.group({
            aggregationLevelName: level.name,
            variableDataForLevel: this.fb.array(this.createVarDataControls(varDatas))
        });

        return group;
    }

    createVarDataControls(varData: IVarData[]): any[] {
        let array: any[] = [];

        for (let vData of varData) {
            let group: FormGroup;

            group = this.fb.group({
                variableDataId: vData.variableDataId,
                value: vData.value
            });

            array.push(group);
        }

        return array;
    }



    disableSubmit() {
        return (!this.varDataForm.valid);
    }

    onSubmit() {
    }
}

我认为问题出在这里:

createVarDataControls(varData: IVarData[]): any[] {
    let array: any[] = [];

    for (let vData of varData) {
        let group: FormGroup;

        group = this.fb.group({
            variableDataId: vData.variableDataId,
            value: vData.value
        });

        array.push(group);
    }

    return array;
}

如果varData为空它将return一个Any[],但我不认为return这是一个错误,因为我不想显示表格上有些空白。

如果 varData 为空,我已将方法 createVarDataControls 编辑为 return 和 FormGroup。这让我继续,但我不认为它回答了我的问题:

createVarDataControls(varData: IVarData[]): any[] {
    let array: any[] = [];

    if ((varData == null) || (varData.length == 0)) {
        let group: FormGroup;

        group = this.fb.group({
            variableDataId: '',
            value: ''
        });

        array.push(group);
    }
    else {
        for (let vData of varData) {
            let group: FormGroup;

            group = this.fb.group({
                variableDataId: vData.variableDataId,
                value: vData.value
            });

            array.push(group);
        }
    }

    return array;
}

有了它,我没有得到任何异常,但它显示了两个空控件,我不希望这样。这仅对确定问题有用。

我找到问题了。如果它可以帮助某人,我想要我的解决方案。

在第二个 FormArray 循环中:

<div formArrayName="variableDataForLevel"
                 *ngFor="let vardata of varDataForm.get('aggLevels')?.controls[0]?.get('variableDataForLevel')?.controls; let rowIndex = index;">

但正确的是:

<div formArrayName="variableDataForLevel"
        *ngFor="let vardata of agLevel.get('variableDataForLevel')?.controls; let rowIndex = index;">

我已将 varDataForm.get('aggLevels')?.controls[0]? 更改为 agLevel

而且我还把方法 createVarDataControls 更改为 return undefined 当没有要显示的变量数据时:

createVarDataControls(varData: IVarData[]): any[] | undefined {
    let array: any[] = [];

    if ((varData == null) || (varData.length == 0)) {
        return undefined;
    }
    else {
        for (let vData of varData) {
            let group: FormGroup;

            group = this.fb.group({
                aggregationLevelConfigurationId: vData.aggregationLevelConfigurationId,
                productionOrderId: vData.productionOrderId,
                variableDataId: vData.variableDataId,
                value: vData.value
            });

            array.push(group);
        }

        return array;
    }
}

尝试失败直到找到解决方案!