[英]Don't show FormArray if it is empty or undefined in a Reactive Form
I've just started to learn Angular 4 doing my first project. 我刚开始学习Angular 4做我的第一个项目。
I have created a Reactive Form to show a form with the following structure: 我创建了一个Reactive Form来显示具有以下结构的表单:
Form (FormGroup)
|
--> aggLevels (FormArray)
|
--> aggregationLevelName (FormControl? I show it in a label)
|
--> variableDataForLevel (FormArray)
|
--> variableDataId (FormControl)
|
--> value (FormControl)
This is the component HTML: 这是组件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>
My problem here is when there isn't any element in variableDataForLevel
FormArray. 我的问题是当
variableDataForLevel
FormArray中没有任何元素时。 I get this message: 我收到这条消息:
ng:///AppModuleShared/VarDataComponent.ngfactory.js:49 ERROR Error: Cannot find control with path: 'aggLevels -> 1 -> variableDataForLevel -> 0'
ng:///AppModuleShared/VarDataComponent.ngfactory.js:49错误错误:找不到路径控件:'aggLevels - > 1 - > variableDataForLevel - > 0'
I have tried to add safe navigation operator ?
我试过添加安全导航操作符
?
at the end of all elements: 在所有元素的末尾:
varDataForm.get('aggLevels')?.controls[0]?.get('variableDataForLevel')?.controls
But I still get the problem. 但我仍然遇到了问题。 FormArray
aggLevels
and variableDataForLevel
aren't undefined because when I create it I instance it. FormArray
aggLevels
和variableDataForLevel
未定义,因为当我创建它时,我实例化它。
What can I do to don't show the FormArray if is empty? 如果为空,我该怎么办才能显示FormArray?
I new with Angular and I have few knowledge about how to fix it. 我是Angular的新手,我对如何修复它知之甚少。
This is the component typescript class for this component: 这是该组件的组件typescript类:
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() {
}
}
I think the problem is here: 我认为问题在于:
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;
}
if varData
is empty it will return a Any[]
, but I don't think return this is an error because I don't want to show something empty on the form. 如果
varData
为空它将返回Any[]
,但我不认为返回这是一个错误,因为我不想在表单上显示空的东西。
I have edited method createVarDataControls
to return a FormGroup
if varData
is empty. 如果
varData
为空,我编辑了方法createVarDataControls
以返回FormGroup
。 This let me continue but I don't think it answers my question: 这让我继续,但我不认为它回答了我的问题:
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;
}
With it I don't get any exception but it shows two empty controls, and I don't want that. 有了它,我没有得到任何异常,但它显示了两个空控件,我不希望这样。 This is only useful to identify the problem.
这仅用于识别问题。
I have found the problem. 我发现了这个问题。 I would like my solution if it can helps someone.
我希望我的解决方案,如果它可以帮助某人。
In the second FormArray
loop: 在第二个
FormArray
循环中:
<div formArrayName="variableDataForLevel"
*ngFor="let vardata of varDataForm.get('aggLevels')?.controls[0]?.get('variableDataForLevel')?.controls; let rowIndex = index;">
But the correct one is: 但正确的是:
<div formArrayName="variableDataForLevel"
*ngFor="let vardata of agLevel.get('variableDataForLevel')?.controls; let rowIndex = index;">
I have changed varDataForm.get('aggLevels')?.controls[0]?
我更改了
varDataForm.get('aggLevels')?.controls[0]?
with agLevel
. 使用
agLevel
。
And also I have changed the method createVarDataControls
to return undefined when there aren't variable data to show on it: 而且,当没有要显示的变量数据时,我还改变了方法
createVarDataControls
以返回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;
}
}
Try and failure until find the solution! 尝试和失败,直到找到解决方案!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.