本文翻译自:How can I select an element in a component template?
Does anybody know how to get hold of an element defined in a component template? 有人知道如何掌握组件模板中定义的元素吗? Polymer makes it really easy with the $
and $$
. 使用$
和$$
可以使Polymer变得非常容易。
I was just wondering how to go about it in Angular. 我只是想知道如何在Angular中进行操作。
Take the example from the tutorial: 从教程中获取示例:
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;
}
}
How do I catch hold of a reference of the p
or input
element from within the class definition? 如何从类定义中抓住对p
或input
元素的引用?
#1楼
参考:https://stackoom.com/question/2DAxR/如何在组件模板中选择元素
#2楼
You can get a handle to the DOM element via ElementRef
by injecting it into your component's constructor: 您可以通过将ElementRef
注入到组件的构造函数中来通过ElementRef
获取DOM元素的句柄:
constructor(myElement: ElementRef) { ... }
Docs: https://angular.io/docs/ts/latest/api/core/index/ElementRef-class.html 文件: https : //angular.io/docs/ts/latest/api/core/index/ElementRef-class.html
#3楼
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) {
// ...
}
}
Example updated to work with the latest version 示例已更新以使用最新版本
For more details on native element, here 有关本机元素的更多详细信息,请单击此处
#4楼
Instead of injecting ElementRef
and using querySelector
or similar from there, a declarative way can be used instead to access elements in the view directly: 代替注入ElementRef
并从那里使用querySelector
或类似的方法,可以使用声明性方法直接访问视图中的元素:
<input #myname>
@ViewChild('myname') input;
element 元件
ngAfterViewInit() {
console.log(this.input.nativeElement.value);
}
StackBlitz example StackBlitz示例
- @ViewChild() supports directive or component type as parameter, or the name (string) of a template variable. @ViewChild()支持将指令或组件类型作为参数,或模板变量的名称(字符串)。
- @ViewChildren() also supports a list of names as comma separated list (currently no spaces allowed
@ViewChildren('var1,var2,var3')
). @ViewChildren()还支持以逗号分隔列表的名称列表(当前不允许使用空格@ViewChildren('var1,var2,var3')
)。 - @ContentChild() and @ContentChildren() do the same but in the light DOM (
<ng-content>
projected elements). @ContentChild()和@ContentChildren()的功能相同,但使用的是DOM(<ng-content>
投影元素)。
descendants 子孙
@ContentChildren()
is the only one that allows to also query for descendants @ContentChildren()
是唯一一个还可以查询后代的人
@ContentChildren(SomeTypeOrVarName, {descendants: true}) someField;
{descendants: true}
should be the default but is not in 2.0.0 final and it's
considered a bug
{descendants: true}
应该是默认值,但不在2.0.0 final中,因此
被认为是错误
This was fixed in 2.0.1 此问题已在2.0.1中修复
read 读
If there are a component and directives the read
parameter allows to specify which instance should be returned. 如果有组件和指令,则read
参数允许指定应返回哪个实例。
For example ViewContainerRef
that is required by dynamically created components instead of the default ElementRef
例如,动态创建的组件而不是默认的ElementRef
需要ViewContainerRef
@ViewChild('myname', { read: ViewContainerRef }) target;
subscribe changes 订阅更改
Even though view children are only set when ngAfterViewInit()
is called and content children are only set when ngAfterContentInit()
is called, if you want to subscribe to changes of the query result, it should be done in ngOnInit()
即使仅在ngAfterViewInit()
时才设置视图子级,而仅在ngAfterViewInit()
时才设置内容子级, ngAfterContentInit()
,如果要订阅查询结果的更改,则应在ngOnInit()
https://github.com/angular/angular/issues/9689#issuecomment-229247134 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));
}
direct DOM access 直接DOM访问
can only query DOM elements, but not components or directive instances: 只能查询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);
}
}
get arbitrary projected content 获得任意的投影内容
See Access transcluded content 请参阅访问包含的内容
#5楼
For people trying to grab the component instance inside a *ngIf
or *ngSwitchCase
, you can follow this trick. 对于试图在*ngIf
或*ngSwitchCase
获取组件实例的*ngSwitchCase
,您可以按照以下技巧进行操作。
Create an init
directive. 创建一个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);
}
}
Export your component with a name such as myComponent
使用诸如myComponent
的名称导出组件
@Component({
selector: 'wm-my-component',
templateUrl: 'my-component.component.html',
styleUrls: ['my-component.component.css'],
exportAs: 'myComponent'
})
export class MyComponent { ... }
Use this template to get the ElementRef
AND MyComponent
instance 使用此模板获取ElementRef
AND MyComponent
实例
<div [ngSwitch]="type">
<wm-my-component
#myComponent="myComponent"
*ngSwitchCase="Type.MyType"
(init)="init($event, myComponent)">
</wm-my-component>
</div>
Use this code in TypeScript 在TypeScript中使用此代码
init(myComponentRef: ElementRef, myComponent: MyComponent) {
}
#6楼
*/
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*/
};
}
}