How can I select an element in a component template?

后端 未结 12 1923
挽巷
挽巷 2020-11-21 06:56

Does anybody know how to get hold of an element defined in a component template? Polymer makes it really easy with the $ and $$.

I was just

相关标签:
12条回答
  • 2020-11-21 07:02

    Note: This doesn't apply to Angular 6 and above as ElementRef became ElementRef<T> with T denoting the type of nativeElement.

    I would like to add that if you are using ElementRef, as recommended by all answers, then you will immediately encounter the problem that ElementRef has an awful type declaration that looks like

    export declare class ElementRef {
      nativeElement: any;
    }
    

    this is stupid in a browser environment where nativeElement is an HTMLElement.

    To workaround this you can use the following technique

    import {Inject, ElementRef as ErrorProneElementRef} from '@angular/core';
    
    interface ElementRef {
      nativeElement: HTMLElement;
    }
    
    @Component({...}) export class MyComponent {
      constructor(@Inject(ErrorProneElementRef) readonly elementRef: ElementRef) { }
    }
    
    0 讨论(0)
  • 2020-11-21 07:06

    Mimimum example for quick usage:

    import { Component, ElementRef, ViewChild} from '@angular/core';
    
    @Component({
      selector: 'my-app',
      template:
      `
      <input #inputEl value="hithere">
      `,
      styleUrls: [ './app.component.css' ]
    })
    export class AppComponent  {
      @ViewChild('inputEl') inputEl:ElementRef; 
    
      ngAfterViewInit() {
        console.log(this.inputEl);
      }
    }
    
    1. Put a template reference variable on the DOM element of interest. In our example this is the #inputEl on the <input> tag.
    2. In our component class inject the DOM element via the @ViewChild decorator
    3. Access the element in the ngAfterViewInit lifecycle hook.

    Note:

    If you want to manipulate the DOM elements use the Renderer2 API instead of accessing the elements directly. Permitting direct access to the DOM can make your application more vulnerable to XSS attacks

    0 讨论(0)
  • 2020-11-21 07:07

    to get the immediate next sibling ,use this

    event.source._elementRef.nativeElement.nextElementSibling
    
    0 讨论(0)
  • 2020-11-21 07:12

    Selecting target element from the list. It is easy to select particular element from the list of same elements.

    component code:

    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 code:

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

    css code:

    .selected {
      color: red;
      background:blue;
    }
    
    0 讨论(0)
  • 2020-11-21 07:15

    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:

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

    element

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

    StackBlitz example

    • @ViewChild() supports directive or component type as parameter, or the name (string) of a template variable.
    • @ViewChildren() also supports a list of names as comma separated list (currently no spaces allowed @ViewChildren('var1,var2,var3')).
    • @ContentChild() and @ContentChildren() do the same but in the light DOM (<ng-content> projected elements).

    descendants

    @ContentChildren() is the only one that allows to also query for descendants

    @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
    This was fixed in 2.0.1

    read

    If there are a component and directives the read parameter allows to specify which instance should be returned.

    For example ViewContainerRef that is required by dynamically created components instead of the default ElementRef

    @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()

    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

    can only query DOM elements, but not components or directive instances:

    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

    0 讨论(0)
  • 2020-11-21 07:18

    You can get a handle to the DOM element via ElementRef by injecting it into your component's constructor:

    constructor(private myElement: ElementRef) { ... }
    

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

    0 讨论(0)
提交回复
热议问题