How can I select an element in a component template?

后端 未结 12 1941
挽巷
挽巷 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:19

    For people trying to grab the component instance inside a *ngIf or *ngSwitchCase, you can follow this trick.

    Create an init directive.

    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

    @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

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

    Use this code in TypeScript

    init(myComponentRef: ElementRef, myComponent: MyComponent) {
    }
    
    0 讨论(0)
  • 2020-11-21 07:19

    In case you are using Angular Material, you can take advantage of cdkFocusInitial directive.

    Example: <input matInput cdkFocusInitial>

    Read more here: https://material.angular.io/cdk/a11y/overview#regions

    0 讨论(0)
  • 2020-11-21 07: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) {
        // ...
      }
    }
    

    Example updated to work with the latest version

    For more details on native element, here

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

    import the ViewChild decorator from @angular/core, like so:

    HTML Code:

    <form #f="ngForm"> 
      ... 
      ... 
    </form>
    

    TS Code:

    import { ViewChild } from '@angular/core';
    
    class TemplateFormComponent {
    
      @ViewChild('f') myForm: any;
        .
        .
        .
    }
    

    now you can use 'myForm' object to access any element within it in the class.

    Source

    0 讨论(0)
  • 2020-11-21 07:27
     */
    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*/
            };
        }
    }
    
    0 讨论(0)
  • 2020-11-21 07:28

    Angular 4+: Use renderer.selectRootElement with a CSS selector to access the element.

    I've got a form that initially displays an email input. After the email is entered, the form will be expanded to allow them to continue adding information relating to their project. However, if they are not an existing client, the form will include an address section above the project information section.

    As of now, the data entry portion has not been broken up into components, so the sections are managed with *ngIf directives. I need to set focus on the project notes field if they are an existing client, or the first name field if they are new.

    I tried the solutions with no success. However, Update 3 in this answer gave me half of the eventual solution. The other half came from MatteoNY's response in this thread. The result is this:

    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');
        }
    }
    

    Since the only thing I'm doing is setting the focus on an element, I don't need to concern myself with change detection, so I can actually run the call to renderer.selectRootElement outside of Angular. Because I need to give the new sections time to render, the element section is wrapped in a timeout to allow the rendering threads time to catch up before the element selection is attempted. Once all that is setup, I can simply call the element using basic CSS selectors.

    I know this example dealt primarily with the focus event, but it's hard for me that this couldn't be used in other contexts.

    UPDATE: Angular dropped support for Renderer in Angular 4 and removed it completely in Angular 9. This solution should not be impacted by the migration to Renderer2. Please refer to this link for additional information: Renderer migration to Renderer2

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