如何在组件模板中选择元素?

Ama*_*pta 463 typescript angular-components angular

有人知道如何获取组件模板中定义的元素吗?聚合物使得它真正用简单的$$$.

我只是想知道如何在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;
    }
}
Run Code Online (Sandbox Code Playgroud)

如何从类定义中捕获por input元素的引用?

Gün*_*uer 848

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

<input #myname>
Run Code Online (Sandbox Code Playgroud)
@ViewChild('myname') input; 
Run Code Online (Sandbox Code Playgroud)

元件

ngAfterViewInit() {
  console.log(this.input.nativeElement.value);
}
Run Code Online (Sandbox Code Playgroud)

StackBlitz的例子

  • @ViewChild()支持指令或组件类型作为参数,或模板变量的名称(字符串).
  • @ViewChildren()还支持以逗号分隔列表的名称列表(当前不允许空格@ViewChildren('var1,var2,var3')).
  • @ContentChild()@ContentChildren()在轻量级DOM(<ng-content>投影元素)中执行相同操作.

后人

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

@ContentChildren(SomeTypeOrVarName, {descendants: true}) someField; 
Run Code Online (Sandbox Code Playgroud)

{descendants: true}应该是默认值,但不是2.0.0 final,它被认为是一个错误
这在2.0.1中得到修复

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

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

@ViewChild('myname', { read: ViewContainerRef }) target;
Run Code Online (Sandbox Code Playgroud)

订阅更改

即使只在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));
}
Run Code Online (Sandbox Code Playgroud)

直接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);
  }
}
Run Code Online (Sandbox Code Playgroud)

获得任意投射内容

请参阅访问已转换的内容

  • 实际上使用`ElementRef`就好了.使用`ElementRef.nativeElement`和`Renderer`也可以.不鼓励****直接访问`ElementRef.nativeElement.xxx`的属性. (29认同)
  • 有角度的团队建议不要使用ElementRef,这是更好的解决方案. (12认同)
  • 如上面*read*部分所述,如果要获取ViewChild元素的nativeElement,则必须执行以下操作:`@ ViewChild('myObj',{read:ElementRef})myObj:ElementRef;` (9认同)
  • 实际上`input`也是一个`ElementRef`,但是你得到了你想要的元素的引用,而不是从主机`ElementRef`中查询它. (7认同)
  • @Natanael我不知道是否或在何处明确记录了这一点,但在问题或其他讨论(也来自Angular团队成员)中经常提到应该避免直接访问DOM.直接访问DOM(这是访问`ElementRef.nativeElement的属性和方法)`,阻止您使用Angulars服务器端呈现和WebWorker功能(我不知道它是否也打破了即将推出的离线模板编译器 - 但我可能不会). (2认同)

Bro*_*cco 195

您可以ElementRef通过将它注入组件的构造函数来获取DOM元素的句柄:

constructor(myElement: ElementRef) { ... }
Run Code Online (Sandbox Code Playgroud)

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

  • `ElementRef`可用(再次?). (23认同)
  • @john啊..好的.你可以尝试这个--`his.element.nativeElement.querySelector('#someElementId')`并将ElementRef传递给像这样的构造函数.`private element:ElementRef,`import lib ...`import {ElementRef} from' @角/芯';` (12认同)
  • [link](https://angular.io/docs/ts/latest/api/core/index/ElementRef-class.html)当需要直接访问DOM时,使用此API作为**最后的手段**.请使用Angular提供的模板和数据绑定.或者,您可以查看Renderer,它提供了可以安全使用的API,即使不支持直接访问本机元素也是如此.依赖于直接DOM访问会在应用程序和渲染层之间产生紧密耦合,这使得无法将两者分开并将应用程序部署到Web工作者中. (9认同)

gdi*_*290 48

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) {
    // ...
  }
}
Run Code Online (Sandbox Code Playgroud)

更新示例以使用最新版本

有关native元素的更多详细信息,请在此处


Nei*_* T. 18

Angular 4+:renderer.selectRootElement与CSS选择器一起使用以访问元素.

我有一个最初显示电子邮件输入的表单.输入电子邮件后,表单将被扩展,以允许他们继续添加与其项目相关的信息.但是,如果它们不是现有客户,则表单将包含项目信息部分上方的地址部分.

截至目前,数据输入部分尚未分解为组件,因此这些部分使用*ngIf指令进行管理.如果它们是现有客户端,我需要将重点放在项目备注字段上,如果它们是新的,则需要将焦点放在第一个名称字段上.

我尝试了解决方案但没有成功.但是,这个答案中的更新3 给了我最终解决方案的一半.另一半来自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');
    }
}
Run Code Online (Sandbox Code Playgroud)

因为我唯一要做的就是将注意力集中在一个元素上,所以我不需要关注变化检测,所以我实际上可以将调用运行到renderer.selectRootElementAngular之外.因为我需要给新部分渲染时间,所以元素部分被包装在超时中以允许渲染线程在尝试元素选择之前赶上时间.完成所有设置之后,我可以使用基本的CSS选择器简单地调用元素.

我知道这个例子主要涉及焦点事件,但我很难在其他情况下使用它.


jsg*_*pil 12

对于试图在一个*ngIf或者内部获取组件实例的人来说*ngSwitchCase,你可以遵循这个技巧.

创建一个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);
    }
}
Run Code Online (Sandbox Code Playgroud)

使用诸如的名称导出组件 myComponent

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

使用此模板获取ElementRefAND MyComponent实例

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

在TypeScript中使用此代码

init(myComponentRef: ElementRef, myComponent: MyComponent) {
}
Run Code Online (Sandbox Code Playgroud)


Han*_*any 10

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

<form #f="ngForm"> 
  ... 
  ... 
</form>
Run Code Online (Sandbox Code Playgroud)

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

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

  • 不要使用任何,类型是ElementRef (3认同)

Nae*_*hir 9

我用过两种方式:

第一种方式:

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

constructor(private myElement: ElementRef) {
this.myElement.nativeElement // <- your direct element reference
}
Run Code Online (Sandbox Code Playgroud)

第二种方式:

@Component({
  selector: 'my-app',
  template:
  `
  <input #input value="enterThere">
  `,
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  @ViewChild('input') input:ElementRef; 

  ngAfterViewInit() {
    console.log(this.input);
  }
Run Code Online (Sandbox Code Playgroud)


Eng*_*abr 8

 */
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*/
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 请提供此代码的一些说明.我们强烈建议不要在没有解释的情况下进行代码转储. (8认同)
  • 这不起作用:通过@ViewChild注释设置的属性仅在ngAfterViewInit生命周期事件之后可用.在这种情况下,访问构造函数中的值将为`inputTxt`生成一个未定义的值. (4认同)

Alu*_*dad 5

:这并不适用于6角以上为ElementRef成为ElementRef<T>T表示的类型nativeElement

我想补充一点,如果您ElementRef按照所有答案的建议使用,那么您将立即遇到ElementRef具有可怕类型声明的问题,看起来像

export declare class ElementRef {
  nativeElement: any;
}
Run Code Online (Sandbox Code Playgroud)

这在 nativeElement 是HTMLElement.

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

import {Inject, ElementRef as ErrorProneElementRef} from '@angular/core';

interface ElementRef {
  nativeElement: HTMLElement;
}

@Component({...}) export class MyComponent {
  constructor(@Inject(ErrorProneElementRef) readonly elementRef: ElementRef) { }
}
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

468032 次

最近记录:

6 年,1 月 前