Cel*_*bes 7 typescript angular2-forms angular2-template angular
假设我从angular2应用程序生成的html如下所示:
<app>
<form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm.value)">
<panel-component>
<mid-component>
<inner-component-with-inputs>
<input/>
<inner-component-with-inputs>
<mid-component>
</panel-component>
<panel-component>
<mid-component>
<inner-component-with-inputs>
<input/>
<inner-component-with-inputs>
<mid-component>
</panel-component>
<!-- many many many fields -->
<button type="submit">Submit</button>
</form>
</app>
Run Code Online (Sandbox Code Playgroud)
如何设置我的外部<form>
以便我可以在提交时验证所有内部输入?我必须通过myForm
通过@Input()
从一路下跌panel-component
到inner-component-with-inputs
?或者还有其他方式吗?
在我的应用程序中,我有一个非常大的形式,有多个面板,子面板,标签,模态等.我需要能够在提交时一次性验证它.
互联网上的所有教程和资源仅涉及跨越一个组件/模板的表单.
Pau*_*tha 12
当涉及父/子关系时,您将在整个Angular源代码中看到的常见模式是父类型,将自身添加为自身的提供者.这样做是允许子组件注入父组件.由于分层DI ,在组件树中只有一个父组件的实例.下面是一个可能的样子
export abstract class FormControlContainer {
abstract addControl(name: string, control: FormControl): void;
abstract removeControl(name: string): void;
}
export const formGroupContainerProvider: any = {
provide: FormControlContainer,
useExisting: forwardRef(() => NestedFormComponentsComponent)
};
@Component({
selector: 'nested-form-components',
template: `
...
`,
directives: [REACTIVE_FORM_DIRECTIVES, ChildComponent],
providers: [formGroupContainerProvider]
})
export class ParentComponent implements FormControlContainer {
form: FormGroup = new FormGroup({});
addControl(name: string, control: FormControl) {
this.form.addControl(name, control);
}
removeControl(name: string) {
this.form.removeControl(name);
}
}
Run Code Online (Sandbox Code Playgroud)
一些说明:
我们使用接口/抽象parent(FormControlContainer
)有几个原因
ParentComponent
从ChildComponent
.孩子不需要知道具体的事情ParentComponent
.所有它知道的是FormControlContainer
和合同有关.ParentComponent
通过接口契约公开那些想要的方法.我们只有做广告 ParentComponent
的FormControlContainer
,因此后者是我们将注入.
我们以the的形式创建一个提供者,formControlContainerProvider
然后将该提供者添加到ParentComponent
.由于分层DI,现在所有孩子都可以访问父母.
如果您不熟悉forwardRef
,这是一篇很棒的文章
现在在孩子(你)你可以做
@Component({
selector: 'child-component',
template: `
...
`,
directives: [REACTIVE_FORM_DIRECTIVES]
})
export class ChildComponent implements OnDestroy {
firstName: FormControl;
lastName: FormControl;
constructor(private _parent: FormControlContainer) {
this.firstName = new FormControl('', Validators.required);
this.lastName = new FormControl('', Validators.required);
this._parent.addControl('firstName', this.firstName);
this._parent.addControl('lastName', this.lastName);
}
ngOnDestroy() {
this._parent.removeControl('firstName');
this._parent.removeControl('lastName');
}
}
Run Code Online (Sandbox Code Playgroud)
IMO,这是一个比FormGroup
通过@Input
s 更好的设计.如前所述,这是整个Angular源的常见设计,所以我认为可以肯定地说这是一种可接受的模式.
如果要使子组件更可重用,可以创建构造函数参数@Optional()
.
以下是我用来测试上述例子的完整资料
import {
Component, OnInit, ViewChildren, QueryList, OnDestroy, forwardRef, Injector
} from '@angular/core';
import {
FormControl,
FormGroup,
ControlContainer,
Validators,
FormGroupDirective,
REACTIVE_FORM_DIRECTIVES
} from '@angular/forms';
export abstract class FormControlContainer {
abstract addControl(name: string, control: FormControl): void;
abstract removeControl(name: string): void;
}
export const formGroupContainerProvider: any = {
provide: FormControlContainer,
useExisting: forwardRef(() => NestedFormComponentsComponent)
};
@Component({
selector: 'nested-form-components',
template: `
<form [formGroup]="form">
<child-component></child-component>
<div>
<button type="button" (click)="onSubmit()">Submit</button>
</div>
</form>
`,
directives: [REACTIVE_FORM_DIRECTIVES, forwardRef(() => ChildComponent)],
providers: [formGroupContainerProvider]
})
export class NestedFormComponentsComponent implements FormControlContainer {
form = new FormGroup({});
onSubmit(e) {
if (!this.form.valid) {
console.log('form is INVALID!')
if (this.form.hasError('required', ['firstName'])) {
console.log('First name is required.');
}
if (this.form.hasError('required', ['lastName'])) {
console.log('Last name is required.');
}
} else {
console.log('form is VALID!');
}
}
addControl(name: string, control: FormControl): void {
this.form.addControl(name, control);
}
removeControl(name: string): void {
this.form.removeControl(name);
}
}
@Component({
selector: 'child-component',
template: `
<div>
<label for="firstName">First name:</label>
<input id="firstName" [formControl]="firstName" type="text"/>
</div>
<div>
<label for="lastName">Last name:</label>
<input id="lastName" [formControl]="lastName" type="text"/>
</div>
`,
directives: [REACTIVE_FORM_DIRECTIVES]
})
export class ChildComponent implements OnDestroy {
firstName: FormControl;
lastName: FormControl;
constructor(private _parent: FormControlContainer) {
this.firstName = new FormControl('', Validators.required);
this.lastName = new FormControl('', Validators.required);
this._parent.addControl('firstName', this.firstName);
this._parent.addControl('lastName', this.lastName);
}
ngOnDestroy() {
this._parent.removeControl('firstName');
this._parent.removeControl('lastName');
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2198 次 |
最近记录: |