J'ai consulté plusieurs publications et documents liés, mais je n'arrive toujours pas à obtenir le comportement attendu de @ViewChild.
En fin de compte, j'essaie de définir la position de défilement d'une div. Cet élément n'est pas un composant, mais une div normale dans mon code HTML.
Pour ce faire, j'essaie d'utiliser @ViewChild pour obtenir l'élément DOM dont j'ai besoin et définir sa valeur de défilement. (En passant, si vous connaissez un meilleur moyen d'y parvenir sans @ViewChild (ou jQuery), les réponses seront très appréciées!)
Pour le moment, @ViewChild ne renvoie qu'un indéfini. En passant par des vérifications factices: - J'accède à mon élément dans AfterViewInit - Je n'ai pas d'autres directives comme * ngIf ou * ngFor sur cet élément.
Voici le contrôleur:
import { Component, AfterViewInit, ViewChild, ElementRef } from '@angular/core';
@Component({
selector: 'portfolio-page',
templateUrl: './portfolio-page.component.html',
styleUrls: ['./portfolio-page.component.scss']
})
export class PortfolioPageComponent implements AfterViewInit{
@ViewChild('gallery-container') galleryContainer: ElementRef;
ngAfterViewInit(){
console.log('My element: ' + this.galleryContainer);
}
}
Et le modèle:
<div id='gallery-container' class='gallery-image-container'>
<div class='gallery-padding'></div>
<img class='gallery-image' src='{{ coverPhotoVm }}' />
<img class='gallery-image' src='{{ imagepath }}' *ngFor='let imagepath of imagesVm' />
</div>
Ma sortie est simple: Mon élément: non défini.
Comme vous pouvez le constater, j'essaie actuellement d'accéder à l'élément par ID, mais j'ai également essayé le nom de la classe. Quelqu'un pourrait-il fournir plus de détails sur les attentes de la requête du sélecteur ViewChild?
J'ai aussi vu des exemples où un hash '#' est utilisé comme identifiant de sélecteur utilisé par @ViewChild - - mais cela provoque une erreur d'analyse de modèle pour moi avec # gallery-container.
Je ne peux penser à rien d'autre qui pourrait se tromper ici. Toute aide est appréciée, merci!
Le code complet est disponible ici: https://github.com/aconfee/KimbyArting/tree/master/client/KimbyArting/components/portfolio-page
Essayez plutôt d’utiliser une référence dans votre modèle:
<div id='gallery-container' #galleryContainer class='gallery-image-container'>
<div class='gallery-padding'></div>
<img class='gallery-image' src='{{ coverPhotoVm }}' />
<img class='gallery-image' src='{{ imagepath }}' *ngFor='let imagepath of imagesVm' />
</div>
Et utilisez le nom de référence comme argument:
@ViewChild('galleryContainer') galleryContainer: ElementRef;
MODIFIER
Oublié de mentionner que toute vue ainsi déclarée n'est disponible qu'une fois la vue initialisée. Ceci se produit pour la première fois dans ngAfterViewInit
(importez et implémentez l'interface AfterViewInit
).
Le nom de la référence ne doit pas contenir de tirets, sinon cela ne fonctionnera pas
Parfois, si le composant n’est pas encore initialisé lorsque vous y accédez, vous obtenez une erreur indiquant que le composant enfant n’est pas défini.
Toutefois, même si vous accédez au composant enfant dans AfterViewInit, parfois @ViewChild renvoyait toujours la valeur null. Le problème peut être causé par la * ngIf ou une autre directive.
La solution consiste à utiliser @ViewChildren à la place de @ViewChild et à abonner l'abonnement aux modifications exécuté lorsque le composant est prêt.
Par exemple, si vous voulez accéder au composant enfant MyComponent dans le composant parent ParentComponent.
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 the child component
});
}
}
S'abonner aux modifications sur
@ViewChildren(MyComponent) childrenComponent: QueryList<MyComponent>
travail confirmé, combiné avec setTimeout()
et notifyOnChanges()
et une vérification minutieuse de null
.
Toute autre approche produit des résultats peu fiables et est difficile à tester.
J'ai eu un problème similaire. Contrairement à vous, mon @ViewChild
a retourné une ElementRef
valide, mais lorsque j'ai essayé d'accéder à sa nativeElement
, c'était undefined
.
Je l'ai résolu en définissant la vue id
comme #content
, pas comme #content = "ngModel"
.
<textarea type = "text"
id = "content"
name = "content"
#content
[(ngModel)] = "article.content"
required></textarea>