为了尝试学习Angular 2,我正在制作一个饮食跟踪器,以配合我妻子和我正在尝试的最新时尚饮食。这本书有几个问题可以通过按钮来解答(你有多饿 - 饥饿,非常饥饿等)以及可选的文本输入。还有基于复选框的问题,加上日期。
我正在尝试创建一个由这些多个组件组成的表单 - 一个用于按钮问题,一个用于复选框问题。请参阅此plunker。
我很好奇的是将组件(每个组件都有自己的表单元素)组合成Daily形式的惯用方法。每个子组件都有表单元素,也使用*ngFor
循环外部文件(question-data.ts
)中的数据。目前,每个组件都有一个Daily表单订阅的事件发射器。
以下是每日表单模板(src/daily.component.ts
):
<form>
<h1>Daily Tracker</h1>
<br>
<legend>Date</legend>
<date-picker (onDataEntered)="dateDataEntered($event)"></date-picker>
<br>
<br>
<button-questions
*ngFor="#b of buttonQuestions"
[btn]="b"
(onDataEntered)="buttonDataEntered($event)">
</button-questions>
<checkbox-questions
*ngFor="#c of checkboxQuestions"
[cbox]="c"
(onDataEntered)="checkboxDataEntered($event)">
</checkbox-questions>
<br>
<input type="submit" value="Submit" class="btn btn-primary">
</form>
然后,例如,buttonQuestions
就像这样呈现(src/button-questions.component.ts
):
<form>
<h1>Daily Tracker</h1>
<br>
<legend>Date</legend>
<date-picker (onDataEntered)="dateDataEntered($event)"></date-picker>
<br>
<br>
<button-questions
*ngFor="#b of buttonQuestions"
[btn]="b"
(onDataEntered)="buttonDataEntered($event)">
</button-questions>
<checkbox-questions
*ngFor="#c of checkboxQuestions"
[cbox]="c"
(onDataEntered)="checkboxDataEntered($event)">
</checkbox-questions>
<br>
<input type="submit" value="Submit" class="btn btn-primary">
</form>
dataEntered()
方法执行此操作(单击任何按钮也会调用此方法):
private dataEntered(): void {
this.btn.inputText = this.inputTextControl.value;
this.onDataEntered.emit(this.btn);
}
Daily
组件然后在其子组件上订阅事件发射器,并将处理最终验证/数据库接口(我仍在尝试学习该部分)。
但是我觉得在子组件上使用原始事件侦听器是错误的方法:例如,我不知道如何将我的子组件上的验证器连接到整个表单上的验证。我也不认为我完全使用内置的Angular 2功能。而且我觉得这不符合松散耦合的原则,正如我所理解的那样。
我的倾向是我应该以某种方式将子组件收集到ControlGroup
组件中的主Daily
中,但我不知道该怎么做。
谢谢!
答案 0 :(得分:1)
我不知道这种方法是否首选,但这是一种方法。子组件可以使用ControlContainer
中的@angular/forms
来访问其父控件的FormGroup
。
父组件TypeScript文件:
// imports go here
@Component({
selector: "app-parent",
templateUrl: "./parent.component.html",
styleUrls: ["./parent.component.css"]
})
export class ParentComponent implements OnInit {
// Just create a typical FormGroup.
fg: FormGroup;
// Instantiate the FormGroup using your preferred method.
constructor(fb: FormBuilder) {
this.fg = this.fb.group({ FirstName: "John", LastName: "Doe" });
}
}
父组件模板文件:
<!-- Bind a form in the parent component to your FormGroup. -->
<form [formGroup]="fg">
<!-- Reference the child component. No need for @Inputs or fancy bindings. -->
<app-child></app-child>
</form>
子组件TypeScript文件:
import { Component } from "@angular/core";
import { ControlContainer } from "@angular/forms";
@Component({
selector: "app-child",
templateUrl: "./child.component.html",
styleUrls: ["./child.component.css"]
})
export class ChildComponent {
// Ask the framework for a ControlContainer whose control property has the goods.
constructor(public controlContainer: ControlContainer) { }
ngOnInit(): void {
}
}
子组件模板文件:
<!-- Finally, bind some top-level element to the imported FormGroup. -->
<fieldset [formGroup]="controlContainer.control">
<legend>Reusable Controls Go Here</legend>
<div>
First Name
<!-- Now, use the FormGroup per normal. -->
<input formControlName="FirstName" type="text" />
</div>
<div>
Last Name
<input formControlName="LastName" type="text" />
</div>
<div>
Accessing the FormGroup
<!-- You can even get fancy. -->
{{ controlContainer.control.get('FirstName')?.errors | json }}
</div>
</fieldset>