Comment puis-je sélectionner un élément dans un modèle de composant?

quelqu'un sait comment obtenir un élément défini dans un modèle de composant? Le polymère le rend très facile avec les $ et $$ .

je me demandais comment procéder en angle.

Prenez l'exemple du tutoriel:

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

Comment puis-je saisir une référence de l'élément p ou input dans la définition de la classe?

331
demandé sur mruanova 2015-09-21 13:34:45

10 réponses

au lieu d'injecter ElementRef et d'utiliser querySelector ou similaire à partir de là, une méthode déclarative peut être utilisée à la place pour accéder directement aux éléments de la vue:

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

élément

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

StackBlitz example

  • @ViewChild () supporte la directive ou le type de Composant paramètre, ou le nom (chaîne de caractères) d'une variable de modèle.
  • @ViewChildren () supporte aussi une liste de noms séparés par des virgules (actuellement pas d'espaces permis @ViewChildren('var1,var2,var3') ).
  • @ContentChild() et @ContentChildren() faire la même chose mais dans la lumière DOM ( "1519100920 projetées" éléments).

descendants

@ContentChildren() est la seule qui permet également de rechercher des descendants

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

{descendants: true} devrait être la valeur par défaut mais n'est pas en 2.0.0 final et c'est considéré comme un bug

Ce montant a été fixé au 2.0.11519200920"

lire

S'il y a un composant et des directives Le paramètre read permet de spécifier quelle instance doit être retournée.

par exemple ViewContainerRef qui est requis par les composants créés dynamiquement au lieu de la valeur par défaut ElementRef

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

abonnez-vous changements

même si les enfants de vue ne sont définis que lorsque ngAfterViewInit() est appelé et les enfants de contenu ne sont définis que lorsque ngAfterContentInit() est appelé, si vous voulez vous abonner les modifications apportées au résultat de la requête, il doit être fait dans les 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));
}

accès DOM direct

peut seulement interroger des éléments DOM, mais pas des composants ou des instances de directive:

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

obtenir de l'arbitraire contenu projeté

voir Access transcluse content

658
répondu Günter Zöchbauer 2018-03-19 07:16:52

vous pouvez obtenir une poignée à L'élément DOM via ElementRef en l'injectant dans le constructeur de votre composant:

constructor(myElement: ElementRef) { ... }

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

176
répondu Brocco 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) {
    // ...
  }
}

exemple mis à jour pour fonctionner avec la dernière version

pour plus de détails sur l'élément natif, ici

39
répondu gdi2290 2017-05-24 14:48:40

angulaire 4+ : Utilisez renderer.selectRootElement avec un sélecteur CSS pour accéder à l'élément.

j'ai un formulaire qui affiche initialement une entrée de courrier électronique. Une fois le courriel entré, le formulaire sera élargi pour leur permettre de continuer à ajouter de l'information relative à leur projet. Toutefois, s'il s'agit de et non de , le formulaire comprendra une section sur l'adresse au-dessus de la section des renseignements sur le projet.

à l'heure actuelle, la partie saisie des données n'a pas été divisée en composantes, de sorte que les sections sont gérées selon les directives *ngIf. Je dois mettre l'accent sur le champ Notes de projet s'il s'agit d'un client existant, ou sur le champ Prénom s'il s'agit d'un nouveau client.

j'ai essayé les solutions, sans succès. Cependant, la mise à jour 3 dans cette réponse m'a donné la moitié de la solution finale. L'autre moitié provient de la réponse de MatteoNY dans ce thread. Le résultat est le suivant:

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

puisque la seule chose que je fais est de mettre l'accent sur un élément, Je n'ai pas besoin de me préoccuper de détection de changement, donc je peux effectivement lancer l'appel à renderer.selectRootElement en dehors de L'angle. Parce que j'ai besoin de donner du temps aux nouvelles sections pour le rendu, la section element est enveloppée dans un timeout pour permettre aux threads de rendu de rattraper le temps avant que la sélection de l'élément ne soit tentée. Une fois que tout cela est mis en place, je peux il suffit d'appeler l'élément en utilisant les sélecteurs CSS de base.

je sais que cet exemple traitait principalement de l'événement focus, mais il est difficile pour moi que cela ne puisse pas être utilisé dans d'autres contextes.

15
répondu Neil T. 2017-05-23 12:02:56

pour les personnes qui tentent de saisir l'instance du composant à l'intérieur d'un *ngIf ou *ngSwitchCase , vous pouvez suivre cette astuce.

créer une directive 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);
    }
}

exportez votre composant avec un nom tel que myComponent

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

utilisez ce modèle pour obtenir le ElementRef et MyComponent instance

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

utilisez ce code à la machine à écrire

init(myComponentRef: ElementRef, myComponent: MyComponent) {
}
12
répondu jsgoupil 2016-12-29 00:21:22

importer le ViewChild décorateur de @angulaire de base, comme suit:

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



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

    class TemplateFormComponent {

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

maintenant vous pouvez utiliser l'objet 'myForm' pour accéder à n'importe quel élément de la classe.

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

7
répondu Hany 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
répondu Eng.Gabr 2017-10-31 08:22:33

je voudrais ajouter que si vous utilisez ElementRef , comme recommandé par toutes les réponses, alors vous allez immédiatement rencontrer le problème que ElementRef a une déclaration de type terrible qui ressemble à

export declare class ElementRef {
  nativeElement: any;
}

c'est stupide dans un environnement de navigateur où nativeElement est un HTMLElement .

Pour contourner cela, vous pouvez utiliser la technique suivante

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

interface ElementRef {
  nativeElement: HTMLElement;
}

@Component({...}) export class MyComponent {
  constructor(@Inject(ErrorProneElementRef) readonly elementRef: ElementRef) { }
}
3
répondu Aluan Haddad 2017-02-11 17:10:46

pour obtenir le prochain frère immédiat ,utilisez ce

event.source._elementRef.nativeElement.nextElementSibling
1
répondu Apoorv 2017-10-12 12:49:37

sélectionnant l'élément cible dans la liste. Il est facile de sélectionner élément particulier de la liste des mêmes éléments.

code composant:

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

code html:

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

code css:

.selected {
  color: red;
  background:blue;
}
1
répondu Sai Goud 2018-03-02 19:39:07