有人知道如何获取组件模板中定义的元素吗?聚合物让$和$$变得很容易。

我只是想知道如何在Angular中实现它。

以教程中的例子为例:

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或输入元素的引用?


当前回答

要获得紧邻的下一个兄弟姐妹,使用这个

event.source._elementRef.nativeElement.nextElementSibling

其他回答

从列表中选择目标元素。从相同的元素列表中选择特定的元素是很容易的。

组件代码:

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代码:

<ul *ngFor="let event of listEvents; let i = index">
   <li  (click)="selectElement(event.name, i)" [class]="event.class">
  {{ event.name }}
</li>

css代码:

.selected {
  color: red;
  background:blue;
}

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

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

元素

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

StackBlitz例子

@ViewChild()支持指令或组件类型作为参数,或模板变量的名称(字符串)。 @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

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

例如,动态创建的组件需要ViewContainerRef,而不是默认的ElementRef

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

订阅的变化

尽管视图子函数只在调用ngAfterViewInit()时设置,而内容子函数只在调用ngAfterContentInit()时设置,如果你想订阅查询结果的更改,应该在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);
  }
}

获取任意投影内容

参见访问传输的内容

如果你正在使用Angular Material,你可以利用cdkFocusInitial指令。

示例:<input matInput cdkFocusInitial>

点击此处阅读更多信息: https://material.angular.io/cdk/a11y/overview#regions

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) {
    // ...
  }
}

示例已更新以使用最新版本

有关本机元素的更多详细信息,请点击这里

注意:这并不适用于Angular 6及以上版本,因为ElementRef变成了ElementRef<T>, T表示nativeElement的类型。

我想补充一点,如果您正在使用ElementRef,正如所有答案所推荐的那样,那么您将立即遇到一个问题,即ElementRef有一个看起来很糟糕的类型声明

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) { }
}