我如何select组件模板中的元素?

有谁知道如何获得在组件模板中定义的元素? 聚合物使$ $和$非常容易。

我只是想知道在Angular 2中如何去做。

以教程中的示例为例:

import {Component} from '@angular/core' @Component({ selector:'display' template:` <input #myname(input)="updateName(myname.value)"/> <p>My name : {{myName}}</p> ` }) export class DisplayComponent { myName: string = "Aman"; updateName(input: String) { this.myName = input; } } 

如何从类定义中捕获“P”或“input”元素的引用?

你可以通过ElementRef把注入到你的组件的构造函数中来获得DOM元素的句柄:

 constructor(myElement: ElementRef) { ... } 

文档: https : //angular.io/docs/ts/latest/api/core/index/ElementRef-class.html

而不是注入ElementRef并使用querySelector或类似的,可以使用声明的方式来直接访问视图中的元素:

 <input #myname> 
 @ViewChild('myname') input; 

元件

 ngAfterViewInit() { console.log(this.input.nativeElement.value); } 

Plunker例子

  • @ViewChild()支持指令或组件types作为参数,或模板variables的名称(string)。
  • @ViewChildren()还支持以逗号分隔的列表的名字列表(当前不允许有空格@ViewChildren('var1,var2,var3') )。
  • @ContentChild()和@ContentChildren()在光DOM( <ng-content>投影元素)中做相同的处理。

后人

@ContentChildren()是唯一允许查询后代的

 @ContentChildren(SomeTypeOrVarName, {descendants: true}) someField; 

{descendants: true}应该是默认的,但不在2.0.0 final中,它被认为是一个bug
这在2.0.1中被修复了

如果有组件和指令,则read参数允许指定应该返回哪个实例。

例如ViewContainerRef是dynamic创build的组件所需的,而不是默认的ElementRef

 @ViewChild('myname', { read: ViewContainerRef }) target; 

订阅更改

即使只在ngAfterViewInit()时设置视图子项,并且仅在ngAfterViewInit()时才设置内容子项,如果要订阅查询结果的更改,则应该在ngOnInit()

https://github.com/angular/angular/issues/9689#issuecomment-229247134

 @ViewChildren(SomeType) viewChildren; @ContentChildren(SomeType) contentChildren; ngOnInit() { this.viewChildren.changes.subscribe(changes => console.log(changes)); this.contentChildren.changes.subscribe(changes => console.log(changes)); } 

直接DOM访问

只能查询DOM元素,而不能查询组件或指令实例:

 export class MyComponent { constructor(private elRef:ElementRef) {} ngAfterViewInit() { var div = this.elRef.nativeElement.querySelector('div'); console.log(div); } // for transcluded content ngAfterContentInit() { var div = this.elRef.nativeElement.querySelector('div'); console.log(div); } } 

获得任意的投影内容

请参阅访问transcluded内容

 import { Component, ElementRef, OnInit } from '@angular/core'; @Component({ selector:'display', template:` <input (input)="updateName($event.target.value)"> <p> My name : {{ myName }}</p> ` }) class DisplayComponent implements OnInit { constructor(public element: ElementRef) { this.element.nativeElement // <- your direct element reference } ngOnInit() { var el = this.element.nativeElement; console.log(el); } updateName(value) { // ... } } 

更新示例以使用最新版本

有关本地元素的更多细节,请点击这里

对于试图抓取*ngIf*ngSwitchCase的组件实例的人,可以按照这个方法。

创build一个init指令。

 import { Directive, EventEmitter, Output, OnInit, ElementRef } from '@angular/core'; @Directive({ selector: '[init]' }) export class InitDirective implements OnInit { constructor(private ref: ElementRef) {} @Output() init: EventEmitter<ElementRef> = new EventEmitter<ElementRef>(); ngOnInit() { this.init.emit(this.ref); } } 

导出你的组件与一个名字,如myComponent

 @Component({ selector: 'wm-my-component', templateUrl: 'my-component.component.html', styleUrls: ['my-component.component.css'], exportAs: 'myComponent' }) export class MyComponent { ... } 

使用此模板来获取ElementRefMyComponent实例

 <div [ngSwitch]="type"> <wm-my-component #myComponent="myComponent" *ngSwitchCase="Type.MyType" (init)="init($event, myComponent)"> </wm-my-component> </div> 

在TypeScript中使用此代码

 init(myComponentRef: ElementRef, myComponent: MyComponent) { } 

Angular 4+ :使用renderer.selectRootElement和CSSselect器来访问元素。

我有一个表单,最初显示一个电子邮件input。 电子邮件input后,表格将被扩展,以便他们继续添加有关他们的项目的信息。 但是,如果他们不是现有的客户,表格将包含项目信息部分上方的地址部分。

到目前为止,数据input部分还没有被分解成组件,所以这些部分是用* ngIf指令来pipe理的。 如果他们是一个现有的客户端,我需要把重点放在项目备注字段上,或者如果他们是新的客户端,则需要关注项目备注字段。

我尝试了没有成功的解决scheme。 然而,在这个答案更新3给了我一半的最终解决scheme。 另一半来自MatteoNY的回应。 结果是这样的:

 import { NgZone, Renderer } from '@angular/core'; constructor(private ngZone: NgZone, private renderer: Renderer) {} setFocus(selector: string): void { this.ngZone.runOutsideAngular(() => { setTimeout(() => { this.renderer.selectRootElement(selector).focus(); }, 0); }); } submitEmail(email: string): void { // Verify existence of customer ... if (this.newCustomer) { this.setFocus('#firstname'); } else { this.setFocus('#description'); } } 

因为我所做的唯一的事情就是把焦点放在一个元素上,所以我不需要关心变化检测,所以我可以在Angular之外调用renderer.selectRootElement 。 因为我需要给新的部分渲染时间,所以元素部分被超时包装,以允许渲染线程在尝试元素select之前赶上时间。 一旦所有的设置,我可以简单地使用基本的CSSselect器调用元素。

我知道这个例子主要涉及焦点事件,但是对于我来说这很难在其他情况下使用。

  */ import {Component,ViewChild} from '@angular/core' /*Import View Child*/ @Component({ selector:'display' template:` <input #myname (input) = "updateName(myname.value)"/> <p> My name : {{myName}}</p> ` }) export class DisplayComponent{ @ViewChild('myname')inputTxt:ElementRef; /*create a view child*/ myName: string; updateName: Function; constructor(){ this.myName = "Aman"; this.updateName = function(input: String){ this.inputTxt.nativeElement.value=this.myName; /*assign to it the value*/ }; } } 

我想补充一点,如果你正在使用ElementRef ,正如所有答案中推荐的,那么你将立即遇到这样的问题: ElementRef有一个糟糕的types声明,看起来像

 export declare class ElementRef { nativeElement: any; } 

这在nativeElement是HTMLElement的浏览器环境中是愚蠢的。

要解决此问题,您可以使用以下技术

 import {Inject, ElementRef as ErrorProneElementRef} from '@angular/core'; interface ElementRef { nativeElement: HTMLElement; } @Component({...}) export class MyComponent { constructor(@Inject(ErrorProneElementRef) readonly elementRef: ElementRef) { } } 

从@ angular / core导入ViewChild装饰器,如下所示:

 <form #f="ngForm"> ... </form> import { ViewChild } myFrom '@angular/core'; class TemplateFormComponent { @ViewChild('f') myForm: any; . . . } 

现在你可以使用'myForm'对象来访问类中的任何元素。

来源: https : //codecraft.tv/courses/angular/forms/template-driven/

得到下一个兄弟姐妹,使用这个

 event.source._elementRef.nativeElement.nextElementSibling