在 angular2 中访问任意 child
Accessing arbitrary child in angular2
我想创建一个 "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>`
})
...
我想使用投影组件的状态来隐藏或显示 "required" 星号和验证 div。据我所知,可以使用 @ContentChild()
和 ngAfterContentInit()
访问投影组件,但我认为,我必须有一个特殊的组件才能使用它。
如果我不知道确切的组件,访问投影组件的控制器的最佳方式是什么?
像这样传递你的控制权
@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;
}
现在您只需更改您使用的每个输入字段的输入,如果需要控制,它会显示*星号。 (希望这就是你想要的)
**代码未编译
您可以在需要传递模板变量名称或组件或指令类型的地方使用@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 {
}
我想创建一个 "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>`
})
...
我想使用投影组件的状态来隐藏或显示 "required" 星号和验证 div。据我所知,可以使用 @ContentChild()
和 ngAfterContentInit()
访问投影组件,但我认为,我必须有一个特殊的组件才能使用它。
如果我不知道确切的组件,访问投影组件的控制器的最佳方式是什么?
像这样传递你的控制权
@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;
}
现在您只需更改您使用的每个输入字段的输入,如果需要控制,它会显示*星号。 (希望这就是你想要的)
**代码未编译
您可以在需要传递模板变量名称或组件或指令类型的地方使用@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 {
}