我如何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 { ... }
使用此模板来获取ElementRef
和MyComponent
实例
<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