Jak Mogę wybrać element w szablonie komponentu?

Czy ktoś wie jak zdobyć element zdefiniowany w szablonie komponentu? Polimer sprawia, że jest to naprawdę łatwe z $ i $$.

Zastanawiałem się, jak to zrobić w Angular.

Weź przykład z samouczka:

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

Jak złapać odniesienie do elementu p lub input z definicji klasy?

Author: mruanova, 2015-09-21

10 answers

Aby uzyskać bezpośredni dostęp do elementów w widoku, można użyć metody deklaratywnej:

Zamiast wstrzykiwać ElementRef i używaćquerySelector lub podobnych stamtąd, można użyć metody deklaratywnej, aby uzyskać bezpośredni dostęp do elementów w widoku:

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

Element

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

Przykład StackBlitz

  • @ViewChild () obsługuje dyrektywę lub typ komponentu jako parametr lub nazwę (string) zmiennej szablonowej.
  • @ViewChildren () obsługuje również listę nazw jako listę rozdzieloną przecinkami (obecnie brak spacji @ViewChildren('var1,var2,var3')).
  • @ ContentChild () i @ContentChildren () robią to samo, ale w świetle DOM (<ng-content> rzutowanych elementów).

Potomkowie

@ContentChildren() jest jedynym, który pozwala również na zapytanie o Potomków

@ContentChildren(SomeTypeOrVarName, {descendants: true}) someField; 

W 2.0.0 final jest to błąd, który jest uważany za błąd.]}
To zostało naprawione w 2.0.1

Czytaj

Jeśli są komponentem i dyrektywami parametr read pozwala określić, która instancja ma zostać zwrócona.

Na przykład ViewContainerRef który jest wymagany przez dynamicznie tworzone komponenty zamiast domyślnego ElementRef

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

Subskrybuj zmiany

Mimo że dzieci widoku są ustawiane tylko wtedy, gdy wywołane jest ngAfterViewInit(), a dzieci zawartości są ustawiane tylko wtedy, gdy wywołane jest ngAfterContentInit(), jeśli chcesz subskrybować zmiany wyniku zapytania, należy to zrobić w 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));
}

Bezpośredni dostęp do DOM

Może tylko odpytywać elementy DOM, ale nie komponenty ani instancje dyrektywy:
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);
  }
}

Pobierz dowolne wyświetlane treści

Zobacz dostęp do transkludowanej treści

 658
Author: Günter Zöchbauer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-19 07:16:52

Możesz uzyskać uchwyt do elementu DOM poprzez ElementRef poprzez wstrzyknięcie go do konstruktora twojego komponentu:

constructor(myElement: ElementRef) { ... }

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

 176
Author: Brocco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-03 16:24:58
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) {
    // ...
  }
}

przykład zaktualizowany do pracy z najnowszą wersją

Aby uzyskać więcej informacji na temat elementu natywnego, tutaj

 39
Author: gdi2290,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-24 14:48:40

Kątowa 4 + : Użyj renderer.selectRootElement z selektorem CSS, aby uzyskać dostęp do elementu.

Mam formularz, który początkowo wyświetla wpis e-mail. Po wprowadzeniu wiadomości e-mail formularz zostanie rozszerzony, aby umożliwić im dalsze dodawanie informacji dotyczących ich projektu. Jeśli jednak są nie istniejącym klientem, formularz będzie zawierał sekcję adresową nad sekcją informacji o projekcie.

Na razie część wprowadzania danych nie została podzielona na komponenty, więc sekcje są zarządzane za pomocą dyrektyw *ngIf. Muszę skupić się na polu uwagi do projektu, jeśli są one istniejącym klientem, lub pole Imię, jeśli są nowe.

Wypróbowałem rozwiązania bez powodzenia. Jednak aktualizacja 3 w ta odpowiedź dała mi połowę ostatecznego rozwiązania. Druga połowa pochodzi z odpowiedzi MatteoNY w Tym wątku. Wynik jest taki:
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');
    }
}

Ponieważ jedyne, co robię, to skupianie się na elemencie, nie muszę zajmuję się wykrywaniem zmian, więc mogę uruchomić połączenie do renderer.selectRootElement poza Angular. Ponieważ muszę dać nowym sekcjom czas na renderowanie, sekcja elementu jest owinięta w limit czasu, aby umożliwić wątkom renderującym nadrobienie czasu przed próbą zaznaczenia elementu. Gdy wszystko jest już ustawione, mogę po prostu wywołać element za pomocą podstawowych selektorów CSS.

Wiem, że ten przykład dotyczył przede wszystkim zdarzenia focus, ale trudno mi, aby nie można było tego użyć w innych konteksty.

 15
Author: Neil T.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:56

Dla osób próbujących pobrać instancję komponentu wewnątrz *ngIf lub *ngSwitchCase, możesz wykonać tę sztuczkę.

Utwórz dyrektywę 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);
    }
}

Eksportuj komponent o nazwie takiej jak myComponent

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

Użyj tego szablonu, aby uzyskać instancję ElementRef i MyComponent

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

Użyj tego kodu w maszynopisie

init(myComponentRef: ElementRef, myComponent: MyComponent) {
}
 12
Author: jsgoupil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-29 00:21:22

Importuj dekorator ViewChild z @angular/ core, tak:

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



 import { ViewChild } from '@angular/core';

    class TemplateFormComponent {

      @ViewChild('f') myForm: any;
    .
    .
    .
    }

Teraz możesz użyć obiektu 'myForm', aby uzyskać dostęp do dowolnego elementu w klasie.

Źródło: https://codecraft.tv/courses/angular/forms/template-driven/

 7
Author: Hany,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-11 12:17:46
 */
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*/
        };
    }
}
 6
Author: Eng.Gabr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-31 08:22:33

Chciałbym dodać, że jeśli używasz ElementRef, zgodnie z zaleceniami wszystkich odpowiedzi, to od razu napotkasz problem, który ElementRef ma okropną deklarację typu, która wygląda jak

export declare class ElementRef {
  nativeElement: any;
}

To jest głupie w środowisku przeglądarki, gdzie nativeElement jest HTMLElement.

Aby to obejść, możesz użyć następującej techniki

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

interface ElementRef {
  nativeElement: HTMLElement;
}

@Component({...}) export class MyComponent {
  constructor(@Inject(ErrorProneElementRef) readonly elementRef: ElementRef) { }
}
 3
Author: Aluan Haddad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-11 17:10:46

Aby uzyskać natychmiastowe następne rodzeństwo, użyj tego

event.source._elementRef.nativeElement.nextElementSibling
 1
Author: Apoorv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-12 12:49:37

Wybór elementu docelowego z listy. Łatwo jest wybrać konkretny element z listy tych samych elementów.

Kod komponentu:

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

Kod Html:

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

Kod Css:

.selected {
  color: red;
  background:blue;
}
 1
Author: Sai Goud,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-02 19:39:07