无法使 Angular Material 具有单一表单和子组件表单的步进器正常工作
Can't get Angular Material Stepper with single form and child component forms working
我正在尝试在我们的应用程序中实现 Angular Material 步进器功能。根据文档 here 我提出了以下解决方案:
civilliability-proposal-detail.component.html
<form [formGroup]="formGroup">
<mat-horizontal-stepper labelPosition="bottom" formArrayName="formArray" #stepper>
<mat-step formGroupName="0" [stepControl]="formArray?.get([0])" [editable]="true">
<div>
<ng-template matStepLabel>{{ 'proposals.details.civilLiability.stepper.details' | translate }}</ng-template>
<app-civilliability-step1 [model]="model.details"></app-civilliability-step1>
<button mat-button matStepperNext type="button">Next</button>
</div>
</mat-step>
<mat-step formGroupName="1" [stepControl]="formArray?.get([1])" [editable]="true">
<div>
<ng-template matStepLabel>{{ 'proposals.details.civilLiability.stepper.antecedents' | translate }}</ng-template>
<!-- <app-civilliability-step2 [model]="model.questionnaire"></app-civilliability-step2> -->
<button mat-button matStepperPrevious type="button">Back</button>
<button mat-button matStepperNext type="button">Next</button>
</div>
</mat-step>
</mat-horizontal-stepper>
</form>
civilliability-proposal-detail.component.ts
get formArray(): AbstractControl | null {
return this.formGroup.get('formArray');
}
constructor(private formBuilder: FormBuilder) {}
ngOnInit() {
this.buildForms();
}
buildForms() {
this.formGroup = this.formBuilder.group({
formArray: this.formBuilder.array([this.buildDetailsForm(), this.buildQuestionnaireForm()])
});
}
buildDetailsForm(): FormGroup {
if (typeof this.model === 'undefined') {
this.model = getEmptyCivilLiabilityRequest();
}
const formGroup = this.formBuilder.group({
horses: new FormControl(this.model.details.horses, Validators.min(0)),
properties: new FormControl(this.model.details.properties, Validators.min(0)),
garages: new FormControl(this.model.details.garages, Validators.min(0)),
...
});
return formGroup;
}
buildQuestionnaireForm(): FormGroup {
const formGroup = this.formBuilder.group({});
return formGroup;
}
civilliability-step1.component.html
<form [formGroup]="formGroup">
<section class="row">
<section class="col-md-4 full-width-form">
<mat-form-field>
<mat-label>{{ 'proposals.details.civilLiability.horses' | translate }}</mat-label>
<input type="number" matInput formControlName="horses" />
<mat-error>{{ formGroup.controls['horses'].getError('server-error') }}</mat-error>
</mat-form-field>
</section>
<section class="col-md-4 full-width-form">
<mat-form-field>
<mat-label>{{ 'proposals.details.civilLiability.terrainsWithTrees' | translate }}</mat-label>
<input type="number" matInput formControlName="terrainsWithTrees" />
<mat-error>{{ formGroup.controls['terrainsWithTrees'].getError('server-error') }}</mat-error>
</mat-form-field>
</section>
<section class="col-md-4 full-width-form">
<mat-form-field>
<mat-label>{{ 'proposals.details.civilLiability.garages' | translate }}</mat-label>
<input type="number" matInput formControlName="garages" />
<mat-error>{{ formGroup.controls['garages'].getError('server-error') }}</mat-error>
</mat-form-field>
</section>
</section>
</form>
基于此我得到了一堆错误,我认为这些错误与我在我的表单中使用子组件这一事实有关,但我不太确定如何解决这个问题。那么,有什么建议吗?
我也读过有人 not 在步进器中使用 formArrayName
,但我似乎找不到这个例子了,所以无法测试是否可行。
我建议在每个单独的步骤组件中声明一个表单组,而不是使用表单数组。这是我的做法:
- 创建一个组件来保留步进器。
- 为每个步骤创建一个组件,并在步骤组件中对其进行初始化。
- 使用 public 组件变量或定义模型来保留用户输入。
- 然后您可以通过数据绑定访问父步进组件中每个步进组件的 public 成员。
我正在尝试在我们的应用程序中实现 Angular Material 步进器功能。根据文档 here 我提出了以下解决方案:
civilliability-proposal-detail.component.html
<form [formGroup]="formGroup">
<mat-horizontal-stepper labelPosition="bottom" formArrayName="formArray" #stepper>
<mat-step formGroupName="0" [stepControl]="formArray?.get([0])" [editable]="true">
<div>
<ng-template matStepLabel>{{ 'proposals.details.civilLiability.stepper.details' | translate }}</ng-template>
<app-civilliability-step1 [model]="model.details"></app-civilliability-step1>
<button mat-button matStepperNext type="button">Next</button>
</div>
</mat-step>
<mat-step formGroupName="1" [stepControl]="formArray?.get([1])" [editable]="true">
<div>
<ng-template matStepLabel>{{ 'proposals.details.civilLiability.stepper.antecedents' | translate }}</ng-template>
<!-- <app-civilliability-step2 [model]="model.questionnaire"></app-civilliability-step2> -->
<button mat-button matStepperPrevious type="button">Back</button>
<button mat-button matStepperNext type="button">Next</button>
</div>
</mat-step>
</mat-horizontal-stepper>
</form>
civilliability-proposal-detail.component.ts
get formArray(): AbstractControl | null {
return this.formGroup.get('formArray');
}
constructor(private formBuilder: FormBuilder) {}
ngOnInit() {
this.buildForms();
}
buildForms() {
this.formGroup = this.formBuilder.group({
formArray: this.formBuilder.array([this.buildDetailsForm(), this.buildQuestionnaireForm()])
});
}
buildDetailsForm(): FormGroup {
if (typeof this.model === 'undefined') {
this.model = getEmptyCivilLiabilityRequest();
}
const formGroup = this.formBuilder.group({
horses: new FormControl(this.model.details.horses, Validators.min(0)),
properties: new FormControl(this.model.details.properties, Validators.min(0)),
garages: new FormControl(this.model.details.garages, Validators.min(0)),
...
});
return formGroup;
}
buildQuestionnaireForm(): FormGroup {
const formGroup = this.formBuilder.group({});
return formGroup;
}
civilliability-step1.component.html
<form [formGroup]="formGroup">
<section class="row">
<section class="col-md-4 full-width-form">
<mat-form-field>
<mat-label>{{ 'proposals.details.civilLiability.horses' | translate }}</mat-label>
<input type="number" matInput formControlName="horses" />
<mat-error>{{ formGroup.controls['horses'].getError('server-error') }}</mat-error>
</mat-form-field>
</section>
<section class="col-md-4 full-width-form">
<mat-form-field>
<mat-label>{{ 'proposals.details.civilLiability.terrainsWithTrees' | translate }}</mat-label>
<input type="number" matInput formControlName="terrainsWithTrees" />
<mat-error>{{ formGroup.controls['terrainsWithTrees'].getError('server-error') }}</mat-error>
</mat-form-field>
</section>
<section class="col-md-4 full-width-form">
<mat-form-field>
<mat-label>{{ 'proposals.details.civilLiability.garages' | translate }}</mat-label>
<input type="number" matInput formControlName="garages" />
<mat-error>{{ formGroup.controls['garages'].getError('server-error') }}</mat-error>
</mat-form-field>
</section>
</section>
</form>
基于此我得到了一堆错误,我认为这些错误与我在我的表单中使用子组件这一事实有关,但我不太确定如何解决这个问题。那么,有什么建议吗?
我也读过有人 not 在步进器中使用 formArrayName
,但我似乎找不到这个例子了,所以无法测试是否可行。
我建议在每个单独的步骤组件中声明一个表单组,而不是使用表单数组。这是我的做法:
- 创建一个组件来保留步进器。
- 为每个步骤创建一个组件,并在步骤组件中对其进行初始化。
- 使用 public 组件变量或定义模型来保留用户输入。
- 然后您可以通过数据绑定访问父步进组件中每个步进组件的 public 成员。