【发布时间】:2019-03-27 15:35:47
【问题描述】:
我有一个嵌套的响应式表单,我想将其拆分为多个组件。
高级形式(父)
advanced.component.ts
我定义了基本表单,但我想避免为父组件中的子组件定义表单模型,因为我认为它们不属于这里。
buildChamberForm() {
return this.formBuilder.group({
_id: [''],
__v: [''],
name: [ '', Validators.required ],
cycle: [ '', Validators.required ],
strains: this.formBuilder.array([])
rules: this.formBuilder.array([])
})
}
buildChambersForm() {
return this.formBuilder.group({
chambers: this.formBuilder.array( [] )
})
}
advanced.component.html
<app-setting-strains [chamberStrains]="chamber.strains" [chamberCycle]="chamber.cycle"></app-setting-strains>
<app-setting-lights [chamberRules]="chamber.rules" [chamberCycle]="chamber.cycle"></app-setting-lights>
<app-setting-fans [chamberRules]="chamber.rules"></app-setting-fans>
设置-粉丝(第一个孩子)
分庭规则分为不同的子组件,例如粉丝规则。
<app-input-rule [chamberRules]="chamberRules" [ruleDevice]="'fan'" placeholder="'e.g. Air circulation (Left)'"></app-input-rule>
输入规则表单(第二个孩子)
在(某些)这些子组件中,使用了输入规则形式。其他子组件使用其他输入组件。
input-rule.component.ts
createRuleForm(device?, trigger?) {
const ruleForm = this.formBuilder.group({
_id: [''],
sensor: [''],
device: [device || ''],
forDetector: [''],
detectorId: [''],
trigger: [trigger || ''],
startTime: [''],
durationHOn: [''],
durationOn: [''], // TODO: this is temporary
timeUnit: [''], // TODO: this is temporary
durationMSOn: [''],
onValue: [''],
offValue: [''],
onPattern: [''],
durationMBlocked: [''],
nightOff: [''],
relay: ['']
})
return ruleForm
}
createRulesForms() {
const rulesForm = this.formBuilder.group({
rules: this.formBuilder.array( [] ) // TODO: validator depending on rule type
})
// console.log("rulesForm", rulesForm)
return rulesForm
}
input-rule.component.html
这是在输入规则组件中使用组件的示例。输入规则组件中有几个输入。
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-8">
<app-input-relay *ngIf="rule.get('relay')" [label]="capitalizeFirstletter(ruleDevice) + 'Relay'" [class]="'tutorial-step'" [relay]="rule.get('relay')" [placeholder]="placeholder"></app-input-relay>
</div>
</div>
输入继电器(第三个孩子),input-relay.component.html
输入继电器是设置规则参数的几个组件之一。
<div class="form-group col-xs-6 col-sm-6" *ngIf="relay.value">
<label>Rename Relay</label>
<input type="text" class="form-control" [ngClass]="class" [formControl]="name" [placeholder]="placeholder" (keyup)="debouncedRename(this.relay.value, this.name.value)"/>
</div>
目标
-
将子表单保留在子组件中,而不是在父组件中定义整个表单。或者,如果这是将所有内容移入表单构建器服务的正确方法。
- 在父表单上使用 submit 方法开始验证所有子表单 => 传递来自子表单的数据
问题
在我当前的设置中,我不能使用 setValue 来初始化高级组件中的表单,因为高级组件不知道子表单,例如FormArray strains 因此会出错:
There are no form controls registered with this array yet.
我可以通过使用patchValue 来解决这个问题,但我认为这是反模式。
-
在 parent.component 中定义表单更好还是应该将所有内容移至具有所有表单构建方法的服务?
1.1 如果我把它留在父母中,该怎么做?
1.2 如果我将它移动到服务中,该服务应该是有状态的并包含表单值,还是最好只在服务中生成表单并像上面的 html 示例中那样通过输入传递它?
1.2.1 我是否也需要输出,我在某处读到反应式表单以某种方式处理这个问题。
这些问题基本上都是一个问题,将复杂的嵌套表单拆分为多个组件的正确方法是什么。
编辑:
这是一个服务的例子:
https://blog.grossman.io/real-world-angular-reactive-forms/
但大多数示例将表单逻辑放入组件中(但它们也没有显示如何在组件之间进行拆分):
- https://angular.io/guide/reactive-forms#generating-form-controls-with-formbuilder
- https://angularfirebase.com/lessons/basics-reactive-forms-in-angular/
- https://malcoded.com/posts/angular-fundamentals-reactive-forms
这个使用输入/输出:
(但我在某处读到这不应该使用响应式表单)
【问题讨论】:
-
嗨,我们(在工作中)一直在研究这个话题,我给出了一个正确的答案,你可能想在这里查看stackoverflow.com/a/55457210/2398593 :)
标签: angular angular-reactive-forms