我想创建一个" my-form-group"组件,由标签,任何类型的输入元素(输入,复选框,...)和验证结果的div组成。 我想使用内容投影在标签后插入输入。像这样:
<form [ngFormModel]="myForm" (ngSubmit)="onSubmit()">
<my-form-group>
<input type="text"
class="form-control"
[ngFormControl]="myForm.controls['name']">
</my-form-group>
<form>
该组件可能如下所示:
@Component({
selector: 'my-form-group',
template: `
<div class="form-group">
<label for="name">Name<span [ngIf]="name.required"> *</span></label>
<ng-content></ng-content>
<div [hidden]="name.valid || name.pristine" class="alert alert-danger">
Please check your input
</div>
</div>`
})
...
我想使用投影组件的状态来隐藏或显示&#34; required&#34;星号和验证div。据我所知,可以使用@ContentChild()
和ngAfterContentInit()
访问投影组件,但我认为,我必须有一个特殊组件才能使用它。
如果我不知道确切的组件,访问投影组件控制器的最佳方法是什么?
答案 0 :(得分:3)
您可以使用@ContentChild()
来传递模板变量的名称或组件或指令的类型。
模板变量的缺点是,组件的用户需要使用正确的名称来应用它,这会使您的组件更难以使用。
父组件(使用<my-form-group>
)需要添加providers: [MyProjectionDirective]
的组件或指令类似,这同样很麻烦。
第二种方法允许解决方法
provide(PLATFORM_DIRECTIVES, {useValue: [MyProjectionDirective], multi: true})
当MyProjectionDirective
有一个与投影内容匹配的选择器(如selector: 'input'
)时,该指令将应用于每个输入元素,您可以查询它。缺点是,该指令随后也应用于Angular应用程序中的任何其他输入元素。
您也不会获得投影组件的组件实例,而是指令。您可以告诉@ContentChild()
获取组件实例,但为此您需要提前知道该类型。
因此,似乎使用模板变量的方法是最佳选择:
使用模板变量的示例
@Component({
selector: 'my-input',
template: `
<h1>input</h1>
<input>
`,
})
export class InputComponent {
}
@Component({
selector: 'parent-comp',
template: `
<h1>Parent</h1>
<ng-content></ng-content>
`,
})
export class ParentComponent {
@ContentChild('input') input;
ngAfterViewInit() {
console.log(this.input);
// prints `InputComponent {}`
}
}
@Component({
selector: 'my-app',
directives: [ParentComponent, InputComponent],
template: `
<h1>Hello</h1>
<parent-comp><my-input #input></my-input></parent-comp>
`,
})
export class AppComponent {
}
答案 1 :(得分:2)
通过你的控制,就像这样
@Component({
selector: 'parent',
directives: [MyFormGroup],
template: `
<form [ngFormModel]="myForm" (ngSubmit)="onSubmit()">
<my-form-group [control]="myForm.controls['name']" controlId="name">
<input type="text"
class="form-control" ngControl="name">
</my-form-group>
<form>
`
})
export class Parent {
@ContentChildren(MyFormGroup) children: QueryList<MyFormGroup>;
ngAfterContentInit() {
console.log(this.children);
}
}
在你的组件中
@Component({
selector: 'my-form-group',
template: `
<div class="form-group">
<label for="{{controlId}}"> {{controlId}} <span [ngIf]="control.hasError('required')"> *</span></label>
<ng-content></ng-content>
<div [hidden]="control.valid || control.pristine" class="alert alert-danger">
Please check your input
</div>
</div>`
})
export class MyFormGroup {
@Input control: Control;
@Input controlId: string;
}
现在您只需更改您使用的每个输入字段的输入,如果需要控制,它将显示* asterick。 (希望这是你想要的)
**代码未编译