web-dev-qa-db-fra.com

@ViewChild renvoie undefined

Pour une raison quelconque, mon @ViewChild dans mon Angular 5 App ne fonctionne pas . Je l'ai défini comme suit dans mon composant:

case-detail.component.html:

<div class="inner-tab-content" #innerTabContent>
    <!-- // more content here -->
</div>

J'ai implémenté @ViewChild dans mon contrôleur (au-dessus du constructeur) comme ceci:

case-detail.component.ts

@ViewChild('innerTabContent') tabContentElement: ElementRef;

Et je veux y accéder ici dans le composant: case-detail.component.ts

ngAfterViewInit() {
    console.log("scroll top: " + this.tabContentElement.nativeElement);
}

J'ai implémenté l'interface AfterViewInit. ngAfterViewInit () est appelé correctement. Cependant, this.tabContentElement est toujours undefined.

Toute aide est grandement appréciée :)

4
dave0688

ViewChild() fonctionne correctement avec la dernière version de plunker Angular avec le scénario que vous décrivez. 

Démonstration dans ce dossier: https://plnkr.co/edit/KzWnkE5Hvp7NUow6YAxy

composant: 

ngAfterViewInit() {
    console.log(this.testView); // correctly outputs the element in console, not undefined
}
  • Vérifiez que ElementRef et ViewChild sont correctement importés de '@ angular/core'

  • Votre élément pourrait tout simplement ne pas être là au moment de AfterViewInit (dans le cas où il y aurait un *ngIf, par exemple. (Semble le cas d'après vos commentaires)

Dans ce dernier cas, vous pouvez utiliser un élément wrapper et ViewChildren, qui émet un événement lorsqu'un nouvel élément enfant est ajouté - pour plus d'informations sur la documentation, cliquez ici: https://angular.io/api/core/ViewChildren

notez qu'il peut y avoir un problème avec div en natif selon cette question: @ViewChildren n'est pas mis à jour avec des éléments DOM ajoutés dynamiquement , mais cela peut être contourné en utilisant un nouveau composant qui encapsule votre div, par exemple.

MODIFIER

Vous pouvez également utiliser un délai d’attente pour que le composant soit rendu. Je dois dire que je trouve cette solution 'sale', mais content que cela fonctionne pour vous :)

7
Pac0

Cependant, même si vous accédez au composant enfant dans la AfterViewInit, le @ViewChild retournait toujours toujours la null. Le problème peut être causé par la *ngIf ou une autre directive.

La solution consiste à utiliser le @ViewChildren au lieu de @ViewChild et à souscrire l'abonnement changes qui est exécuté lorsque le composant est prêt.

Par exemple, si vous voulez accéder au composant enfant ParentComponent dans le composant parent MyComponent.

import { Component, ViewChildren, AfterViewInit, QueryList } from '@angular/core';
import { MyComponent } from './mycomponent.component';

export class ParentComponent implements AfterViewInit
{
  //other code emitted for clarity

  @ViewChildren(MyComponent) childrenComponent: QueryList<MyComponent>;

  public ngAfterViewInit(): void
  {
    this.childrenComponent.changes.subscribe((comps: QueryList<MyComponent>) =>
    {
      // Now you can access to the child component
    });
  }
}
5
Marco Barbero

Une réponse différente à cette question serait parfois, le composant enfant n'est toujours pas rendu, lorsque vous y accédez. Pour moi, c'était dû à un * ngIf, de sorte que la composante enfant n'y est toujours pas. À titre d'exemple, 

<div *ngIf="check">
   <app-child-item></app-child-item>
</div>

Et dans votre fichier .ts parent, vous essayez d'accéder à childItem alors que check est défini sur false.

0
dilantha111