How can I select an element in a component template?
有人知道如何获取组件模板中定义的元素吗? 使用
我只是想知道如何在Angular中实现它。
以教程为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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; } } |
如何从类定义中捕获
可以使用声明方式代替直接访问视图中的元素,而不是从那里注入
1 | <input #myname> |
1 | @ViewChild('myname') input; |
元件
1 2 3 | ngAfterViewInit() { console.log(this.input.nativeElement.value); } |
StackBlitz的例子
- @ViewChild()支持指令或组件类型作为参数,或模板变量的名称(字符串)。
-
@ViewChildren()还支持以逗号分隔列表的名称列表(当前不允许空格
@ViewChildren('var1,var2,var3') )。 -
@ContentChild()和@ContentChildren()在轻量级DOM(
投影元素)中执行相同的操作。
后人
1 | @ContentChildren(SomeTypeOrVarName, {descendants: true}) someField; |
<击>
击>
这是在2.0.1中修复的
读
如果有组件和指令,
例如,动态创建的组件而不是默认的
1 | @ViewChild('myname', { read: ViewContainerRef }) target; |
订阅更改
即使只在调用
https://github.com/angular/angular/issues/9689#issuecomment-229247134
1 2 3 4 5 6 7 | @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元素,但不能查询组件或指令实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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); } } |
获得任意投射内容
请参阅访问已转换的内容
您可以通过将
1 | constructor(myElement: ElementRef) { ... } |
文档:https://angular.io/docs/ts/latest/api/core/index/ElementRef-class.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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) { // ... } } |
更新示例以使用最新版本
有关native元素的更多详细信息,请在此处
Angular 4+:
将
我有一个最初显示电子邮件输入的表单。输入电子邮件后,表格将被扩展,以允许他们继续添加与其项目相关的信息。但是,如果它们不是现有客户,则表单将包含项目信息部分上方的地址部分。
截至目前,数据输入部分尚未分解为组件,因此这些部分使用* ngIf指令进行管理。如果它们是现有客户端,我需要将重点放在项目备注字段上,如果它们是新的,则需要将焦点放在第一个名称字段上。
我尝试了解决方案但没有成功。但是,这个答案中的更新3给了我最终解决方案的一半。另一半来自MatteoNY在这个帖子中的回应。结果是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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之外运行对
我知道这个例子主要涉及焦点事件,但我很难在其他情况下使用它。
对于试图在
创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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); } } |
使用诸如
1 2 3 4 5 6 7 | @Component({ selector: 'wm-my-component', templateUrl: 'my-component.component.html', styleUrls: ['my-component.component.css'], exportAs: 'myComponent' }) export class MyComponent { ... } |
使用此模板获取
1 2 3 4 5 | <wm-my-component #myComponent="myComponent" *ngSwitchCase="Type.MyType" (init)="init($event, myComponent)"> </wm-my-component> |
在TypeScript中使用此代码
1 2 | init(myComponentRef: ElementRef, myComponent: MyComponent) { } |
从
HTML代码:
1 2 3 4 | <form #f="ngForm"> ... ... </form> |
TS代码:
1 2 3 4 5 6 7 8 9 | import { ViewChild } from '@angular/core'; class TemplateFormComponent { @ViewChild('f') myForm: any; . . . } |
现在你可以使用'myForm'对象来访问类中的任何元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | */ 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*/ }; } } |
我想补充一点,如果你按照所有答案的建议使用
1 2 3 | export declare class ElementRef { nativeElement: any; } |
这在nativeElement是
要解决此问题,您可以使用以下技术
1 2 3 4 5 6 7 8 9 | import {Inject, ElementRef as ErrorProneElementRef} from '@angular/core'; interface ElementRef { nativeElement: HTMLElement; } @Component({...}) export class MyComponent { constructor(@Inject(ErrorProneElementRef) readonly elementRef: ElementRef) { } } |
从列表中选择目标元素。从相同元素的列表中选择特定元素很容易。
组件代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | export class AppComponent { title = 'app'; listEvents = [ {'name':'item1', 'class': ''}, {'name':'item2', 'class': ''}, {'name':'item3', 'class': ''}, {'name':'item4', 'class': ''} ]; selectElement(item: string, value: number) { console.log("item="+item+" value="+value); if(this.listEvents[value].class =="") { this.listEvents[value].class='selected'; } else { this.listEvents[value].class= ''; } } } |
HTML代码:
1 2 3 4 5 | <ul *ngFor="let event of listEvents; let i = index"> <li (click)="selectElement(event.name, i)" [class]="event.class"> {{ event.name }} </li> |
css代码:
1 2 3 4 | .selected { color: red; background:blue; } |
为了得到下一个兄弟,请使用它
1 | event.source._elementRef.nativeElement.nextElementSibling |