我拥有的:
我正在构建一个离子2应用程序,并构建了一个基本的角2组件,其中包含
我将把它称为我的输入组件。
我有一个页面组件,上面有一个表单,目前有文本输入。1常规输入(密码)和1输入包装在我的输入组件(用户名)。
这是我的页面组件的相关部分
ngOnInit() {
this.loginForm = this.formBuilder.group({
username: ['', Validators.required],
password: ['', Validators.required]
});
}这是页面组件模板
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
<!-- My input component -->
<aw-input-text id="username" name="Username" [formInput]="loginForm.controls.username"></aw-input-text>
<!-- A standard input control -->
<ion-item [class.error]="loginForm.controls.password.errors">
<ion-label floating>Password</ion-label>
<ion-input type="text" value="" name="password" formControlName="password"></ion-input>
<p *ngIf="loginForm.controls.password.errors">This field is required!</p>
</ion-item>
<button type="submit" class="custom-button" [disabled]="!loginForm.valid" block>Login</button>
</form>这是我的输入组件的模板
<!-- Component template -->
<form [formGroup]="formGroup">
<ion-item>
<ion-label floating>{{inputName}}</ion-label>
<ion-input type="text" formControlName="inputValue"></ion-input>
<p *ngIf="!formGroup.controls.inputValue.valid">This field is required!</p>
</ion-item>
</form>,这是输入组件
import {Component, Input} from '@angular/core';
import {FormBuilder} from '@angular/forms';
@Component({
selector: 'aw-input-text',
templateUrl: 'build/shared/aw-input-text/aw-input-text.html'
})
export class AwInputText {
@Input('formInput')
public formInput;
@Input('name')
public inputName;
public formGroup;
constructor(private formBuilder: FormBuilder) {
}
ngOnInit() {
this.formGroup = this.formBuilder.group({
inputValue: this.formInput
});
}
}组件正确呈现。
问题:
组件中的输入不会更新它所处表单的有效状态。
当我填写用户名时,这个密码就会生效。
当我填写密码时,用户名仍然无效。
所以表单可以看到输入组件的有效状态,只是改变有效状态的输入组件不触发要更新的表单。
可能的解决方案1
如本文所述
https://scotch.io/tutorials/how-to-build-nested-model-driven-forms-in-angular-2
https://plnkr.co/edit/clTbNP7MHBbBbrUp20vr?p=preview
我可以修改我的页面组件以创建一个窗体组,其中包含一个嵌套的窗体组,用于我想要在输入组件中使用的每个窗体控件。
ngOnInit() {
this.loginForm = this.formBuilder.group({
username: this.formBuilder.group({
username: ['', Validators.required],
}),
password: ['', Validators.required],
});
}这个解决方案适合在本文中添加一个输入控件数组的场景,但在我的例子中,我认为这感觉很麻烦。
可能的解决方案2
我考虑过的另一个黑客解决方案是使用来自我的输入组件的@output指令来触发页面组件上的事件,每当更新输入组件时,该事件就会刷新表单。
更新输入组件
this.formGroup.controls.inputValue.valueChanges.subscribe(value => {
this.formUpdated.emit({
value: value
})
});更新到页面组件
public onUpdated(value){
this.loginForm.updateValueAndValidity();
}和更新页面组件模板。
<aw-input-text id="username" name="Username" (updated)="onUpdated($event)" [formInput]="loginForm.controls.username"></aw-input-text>这确实为我提供了所需的功能,但我认为,在每个表单页面上设置一个事件处理程序来使输入组件正常工作似乎也有点麻烦。
问题
是否有一种方法可以使组件更新它所处表单的有效状态(请记住,我希望在每个表单中多次重复使用该组件),而不必求助于上述解决方案。
发布于 2016-11-09 01:00:47
谢谢你们的回答。最后,我们创建了两个组件,一个自定义表单组件和一个自定义输入组件。
我们在自定义表单组件中嵌套尽可能多的自定义输入组件,而自定义表单组件使用@ContentChildren来识别和注册所有的子定制输入组件。
这样,我们就不必将表单传递到每个输入中,而且对于每个输入,我们也不会有一堆嵌套的表单组。
// Each CustomInputText component exposes a FormControl and
// a control definition which has additional info about the control
@ContentChildren(CustomInputText, {descendants: true})
public customInputComponents: QueryList<CustomInputText>;
private initialised;
public ngAfterContentChecked() {
// Only initialise the form group once
if (!this.initialised) {
this.initialised = true;
this.customInputComponents.forEach((input)=>{
this.formGroup.addControl(input.controlDefinition.id, input.formControl);
});
}
}发布于 2016-09-26 07:43:54
您可以将@Input loginForm转换为嵌套组件,比如parentForm。然后在子组件init上将嵌套的formGroup注册到parentForm,然后在子组件销毁时取消注册。
发布于 2016-09-26 20:16:42
我在我的例子中所做的(嵌套的动态形式)在某种程度上类似于Marcin的响应。
我将现有的FormGroup作为parentForm传递,我的Component视图如下所示:
<fieldset [formGroup]="parentForm">
<label *ngIf="label" [attr.for]="key">{{label}}</label>
<input [id]="key" [type]="type" [formControlName]="key" />
</fieldset>这符合我的需要。希望它也能帮到你。
更新:我创建了一个加速动态表单创建的库。您可以看看我是如何使用这个答案的:https://www.npmjs.com/package/dorf
https://stackoverflow.com/questions/39629959
复制相似问题