在angular2中访问任意子项

时间:2016-04-27 06:13:21

标签: angular angular2-template angular2-directives

我想创建一个" 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()访问投影组件,但我认为,我必须有一个特殊组件才能使用它。

如果我不知道确切的组件,访问投影组件控制器的最佳方法是什么?

2 个答案:

答案 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 {
}

Plunker example

答案 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。 (希望这是你想要的)

**代码未编译