如何在Angular 2中获得与ElementRef相关的组件的引用

时间:2016-10-07 03:38:07

标签: angular

我的模板中有这个组件:

<vector-editor  #scaleControl
                [x]="scaleX"
                [y]="scaleY"
                [z]="scaleZ" >               
</vector-editor>

vector-editor具有以下结构:

export class VerticeControlComponent implements OnInit
{
    @Input() x: number;
    @Input() y: number;
    @Input() z: number;

    ...
}

在我的应用程序中,我使用

获取对#scaleControl的引用
@ViewChild('scaleControl') scaleControl: ElementRef;

现在,如果我将scaleControl输出到控制台,我会得到以下结果:

enter image description here

可以看出,引用不是null,并且我的组件的所有属性都在那里。我想访问这些属性,但在代码中,scaleControl的实际类型为ElementRef,而不是VectorEditorControl,如输出中所示。因此,TypeScript不允许我使用this.scaleControl.x

我也尝试像这样投射ElementRef

var temp = <VectorEditorControl>this.scaleControl

但是我收到错误告诉我,我无法将ElementRef投提VectorEditorControl

最后,我试图访问this.scaleControl.nativeElement,但它未定义......

我在这里缺少什么?

3 个答案:

答案 0 :(得分:80)

您应该了解使用@ViewChild属性装饰器的以下内容。

它使用以下元数据属性:

  • 选择器 - 用于查询的指令类型或名称。
  • 阅读 - 从查询的元素中读取不同的标记。

来自源代码:

export interface ViewChildDecorator {
  /**
   * You can use ViewChild to get the first element or the directive matching 
   * the selector from the
   * view DOM. If the view DOM changes, and a new child matches the selector,
   * the property will be updated.
   *
   * View queries are set before the `ngAfterViewInit` callback is called.
   *
   * **Metadata Properties**:
   *
   * * **selector** - the directive type or the name used for querying.
   * * **read** - read a different token from the queried elements.
   */
  (selector: Type<any>|Function|string, {read}?: {read?: any}): any;
  new (selector: Type<any>|Function|string, {read}?: {read?: any}): ViewChild;
}

如果您未提供read参数,@ViewChild()将返回:

  • 组件实例,如果有。
  • 如果没有应用任何组件,则
  • ElementRef实例
  • 如果设置了读取属性 ,则
  • 来自查询元素的不同令牌

因此,如果你想从儿童角色2组件ElementRef获得VerticeControlComponent,你需要明确告诉使用read: ElementRef

@ViewChild('scaleControl', {read: ElementRef}) scaleControl: ElementRef;

然后在ngAfterViewInit挂钩或更高版本中,您可以编写this.scaleControl.nativeElement来获取DOM元素。

更新

我早写的:

  
      如果设置了读取属性 ,则
  • 来自查询元素的不同令牌   

现在我想添加我们可以阅读的内容:

  • <强> ElementRef

  • <强> TemplateRef

  • <强> ViewContainerRef

  • <强>提供商

Provider在这里意味着什么?

这意味着如果我们在特定元素上定义了任何提供者(在组件或指令中),那么我们就可以读取它。

@Component({
  selector: 'child',
  template: `
   <h2>I'm child</h2>
  `,
  providers: [
    {
      provide: 'test', useValue: 'x'
    }
  ]
})
export class ChildComponent {

}

所以在这个组件的消费者中我们可以写

@ViewChild(ChildComponent, { read: 'test' }) providerToken: string;

获取值x

<强> Example

另见:

答案 1 :(得分:3)

在撰写本文时,我建议使用以下方法:

@ViewChild('scaleControl') scaleControl: ElementRef<VerticeControlComponent>;

然后您可以访问两种类型。

  • ElementRef:使用scaleControl
  • VerticeControlComponent:使用scaleControl.nativeElement

答案 2 :(得分:1)

我有两次这个错误。一旦进入我的主代码,第二次进入测试代码(规范)。

两次都缺少一些参考。 Angular编译器(转换器)在编译期间没有显示任何错误但稍后,悄悄地没有提供

的参考
  1. 我第一次在主代码abc.component.ts中遇到此错误。我记得这一次,我们在这个abc.component.ts中正确地包含了这个孩子所需的引用。这个子组件来自另一个模块。仅在此子组件未包含在module.ts文件中

    之后才解决该错误

    声明:[VectorEditorComponent,....],

  2. 第二次我们在spec文件中遇到此问题。我试图验证一些期望应该设置子组件的属性。我没有获得子组件的实例,而是获得了ElementRef。这里再次没有编译错误。这里的问题略有不同。我使用过No_Errors_Schema。因此,虽然我们没有在spec文件中包含该组件,但angular并没有抱怨,而是设置了ElementRef而不是子组件。导入模块时,错误消失,并在spec文件的testbed设置中提供。

  3. 在第二种情况下,我可以理解这是由于没有错误架构。但在第一种情况下,我认为Angular团队需要改进。没有任何关于为什么没有提供组件但提供ElementRef的提示。