50 votes

Quels sont tous les sélecteurs valides pour ViewChild et ContentChild?

Je suis à la recherche pour obtenir une liste complète des sélecteurs je peux utiliser pour l'accès de l'enfant composants / éléments du DOM via @ViewChild et @ContentChild.

Dire que j'ai un enfant HelloComponent:

Je sais que je peux ajouter un modèle #ref et d'interroger, comme:

<hello #myHello></hello>

@ViewChild('myHello') myHello: HelloComponent;

Ou je peux regarder de ce composant directement (sans passer par le modèle #ref):

@ViewChild(HelloComponent) myHello: HelloComponent;

Dans cette question, il est mentionné que l'on peut utiliser les sélecteurs suivants:

nous sommes actuellement en charge un sous-ensemble de sélecteurs CSS:
* élément de sélecteurs
* sélecteur d'attribut (y compris les valeurs)
* :n'est pas(...) pseudo-sélecteur
* combinaison de ceux-ci (y compris ,)

Mais quand je l'ai testé dans Stackblitz à vérifier (voici le lien), je n'ai pas pu obtenir l'un des trois premiers à travailler. (Cochez la console pour voir undefined pour les types de sélecteurs je ne pouvais pas obtenir de travail. Je ne suis pas sur si je fais quelque chose de mal avec les sélecteurs, ou si la liste est différente.)

Donc, ce qui sélecteurs va fonctionner? Aussi, la liste est la même pour @ViewChild, @ContentChild, @ViewChildren, et @ContentChildren?

98voto

yurzui Points 85802

Tout d'abord, comme @JB Nizet a déjà mentionné dans les commentaires le commentaire en question est faux: il n'a rien à voir avec la requête sélecteur, mais se réfère plutôt à la directive sélecteur.

Examinons ce type de sélecteurs nous pouvons utiliser pour les requêtes.

Angulaire de la documentation les états que pour les requêtes:

sélecteur de - la directive type ou le nom utilisé pour l'interrogation.

La directive de type

Il semble qu'il devrait être clair pour tous ceux qui (1) nous pouvons interroger les classes, ornée d' @Component ou @Directive décorateur.

@Component({
  selector: 'some-comp',
  template: '...'
})
export class SomeComp {}

@Directive({
  selector: '[someDir]'
})
export class SomeDir {}

@Component({
  selector: 'host-comp',
  template: `
    <some-comp someDir></some-comp>
  `
})
export class HostComp {
  @ViewChild(SomeComp) someComp: SomeComp;
  @ViewChild(SomeDir) someDir: SomeDir;
}

Le nom utilisé pour l'interrogation

Comme pour moi, c'est déroutant description.

Comme il s'est avéré que le nom est ici (2) le nom du modèle de référence de la variable qui est une chaîne de caractères:

@Component({
  selector: 'host-comp',
  template: `
    <some-comp #someComp></some-comp>
  `
})
export class HostComp {
  @ViewChild('someComp') someComp: SomeComp;
}

nous pourrions nous retrouver ici, mais il est temps de prendre un coup d'oeil à angulaires code source et de le plonger un peu plus profondément.

Caché comportement

Regardons le code qui angulaire compilateur utilise pour lire les métadonnées de requête:

private _queryVarBindings(selector: any): string[] { return selector.split(/\s*,\s*/); }

private _getQueryMetadata(q: Query, propertyName: string, typeOrFunc: Type|Function):
      cpl.CompileQueryMetadata {
  let selectors: cpl.CompileTokenMetadata[];
  if (typeof q.selector === 'string') {
    selectors =
        this._queryVarBindings(q.selector).map(varName => this._getTokenMetadata(varName));
  } else {
    if (!q.selector) {
      this._reportError(
          syntaxError(
              `Can't construct a query for the property ...`),
          typeOrFunc);
      selectors = [];
    } else {
      selectors = [this._getTokenMetadata(q.selector)];
    }
}

De le code précédent, nous pouvons conclure que:

Nous allons appliquer nos connaissances de code ci-dessus.

Nous (3) peut interroger plusieurs valeurs à l'aide de plusieurs modèle les variables de référence divisé par ,:

@Component({
  selector: 'a',
  template: '...'
})
export class A {}

@Component({
  selector: 'b',
  template: '...'
})
export class B {}

@Component({
  selector: 'host-comp',
  template: `
    <a #a></a>
    <b #b></b>
  `
})
export class HostComp {
  @ViewChildren('a, b') components;

  ngAfterViewInit() {
    console.log(this.components); // [A, B]
  }
}

(4) le Fournisseur défini sur un composant ou de la directive peut être consulté. (voir aussi l'exemple ajouté par @Ilia Volk)

@Component({
  selector: 'a',
  template: '...',
  providers: [SomeService]
})
export class A {}

@Component({
  selector: 'host-comp',
  template: `<a></a>`
})
export class HostComp {
  @ViewChild(SomeService) someService: SomeService;
}

Depuis la chaîne peut être un jeton pour les fournisseurs que nous pouvons (5) de la requête de plusieurs fournisseurs qui ont été définis par le biais de la chaîne de jeton

@Component({
  selector: 'a',
  providers: [{ provide: 'tokenA', useValue: 'TokenAValue' }],
  template: '...'
})
export class A { }

@Component({
  selector: 'b',
  providers: [{ provide: 'tokenB', useValue: 'TokenBValue' }],
  template: '...'
})
export class B { }

@Component({
  selector: 'host-comp',
  template: `
    <a #a></a>
    <b #b></b>
  `
})
export class HostComp {
  @ViewChildren('tokenA, tokenB') stringTokenProviders;

  ngAfterViewInit() {
    console.log(this.stringTokenProviders); // ['TokenAValue', 'TokenBValue']
  }
}

La prochaine escale est l'endroit dans le package de base où angulaire nous renvoie la valeur de requête particulière:

export function getQueryValue(
    view: ViewData, nodeDef: NodeDef, queryValueType: QueryValueType): any {
  if (queryValueType != null) {
    // a match
    switch (queryValueType) {
      case QueryValueType.RenderElement:
        return asElementData(view, nodeDef.nodeIndex).renderElement;
      case QueryValueType.ElementRef:
        return new ElementRef(asElementData(view, nodeDef.nodeIndex).renderElement);
      case QueryValueType.TemplateRef:
        return asElementData(view, nodeDef.nodeIndex).template;
      case QueryValueType.ViewContainerRef:
        return asElementData(view, nodeDef.nodeIndex).viewContainer;
      case QueryValueType.Provider:
        return asProviderData(view, nodeDef.nodeIndex).instance;
    }
  }
}

RenderElement dans le code ci-dessus est certains jeton interne qui nous ne permet pas d'interroger.

ElementRef peut être interrogée par l'intermédiaire du modèle de référence de la variable ou en utilisant l' option de lecture

(6) TemplateRef peut être interrogée par l'intermédiaire d' selector:

@Component({
  selector: 'host-comp',
  template: `
    <ng-template></ng-template>
  `
})
export class HostComp {
  @ViewChild(TemplateRef) template;
}

et bien sûr, ainsi que ViewContainerRef par read option.

Provider peut être obtenue par l'utilisation de read option ou par l'intermédiaire du sélecteur de celui que j'ai décrit dans le milieu de cette réponse.

11voto

Xelian Points 1006

EN vue courte enfant Vous pouvez utiliser la directive anglulaire, le sélecteur de composants, la variable de référence

entrez la description de l'image ici

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X