83 votes

Comment accéder à une constante dans un composant et un service Angular 2 ?

J'ai un fichier de constantes constants.ts :

export const C0NST = "constant";

J'y accède dans un service certains.service.ts comme ça :

import { C0NST } from './constants';

console.log(C0NST); // "constant"

Cependant, lorsque j'y accède dans un modèle de composant :

some.component.ts :

import { C0NST } from './constants';

certains.composants.html :

{{ C0NST }} <!-- Outputs nothing -->

Cependant, définir un membre dans la classe du composant fonctionne :

some.component.ts

public const constant = C0NST;

certains.composants.html

{{ constant }} <!-- constant -->

Je ne comprends pas pourquoi j'ai pu accéder à la constante importée directement dans la classe de service mais pas dans le modèle de composant alors que je l'ai importée dans la classe de composant.

83voto

Horia Coman Points 6847

Dans Angular2, le modèle ne peut accéder qu'aux champs et méthodes de la classe du composant. Tout le reste est hors limites. Cela inclut les éléments qui sont visibles par la classe du composant.

La façon de contourner ce problème est de disposer d'un champ dans le composant, qui fait simplement référence à la constante, et de l'utiliser à la place.


C'est une limitation de la conception, mais peut-être devriez-vous réfléchir davantage à la raison pour laquelle vous avez besoin d'une constante dans le modèle en premier lieu. Habituellement, ces éléments sont utilisés par les composants eux-mêmes, ou les services, mais pas par le modèle.

0 votes

Merci Horia. J'ai une liste d'URL de GIFs que je dois obtenir de Giphy et je les enregistre dans le fichier de constantes. J'ai l'intention de les utiliser dans toute l'application à travers les composants. Quelle est la meilleure méthode selon vous ?

1 votes

@KabirRoy Cela semble être une chose décente à faire en fait. Si vous avez un nombre relativement faible d'images, vous pourriez en fait créer des composants pour elles, et utiliser l'URL giphy directement dans la source (comme vous le feriez pour une ressource fournie par votre application). Mais cela semble être une bonne approche, quoi qu'il en soit.

1 votes

Que dire des chaînes de formatage "mm/dd/yyyy" qui sont transversales à toute l'application, pourquoi ne devraient-elles pas être accessibles dans un modèle ?

70voto

Shin Points 10934

Étant donné que dans le modèle du composant, vous ne pouvez utiliser que des attributs de la classe du composant, vous ne pouvez pas utiliser directement de constantes externes (ou de variables externes).

La méthode la plus élégante que j'ai trouvée jusqu'à présent est la suivante :

import { MY_CONSTANT } from '../constants';

@Component({
  // ...
})
export class MyTestComponent implements OnInit {

  readonly MY_CONSTANT = MY_CONSTANT;

  // ...
}

qui crée simplement un nouvel attribut MY_CONSTANT à l'intérieur de la classe du composant. Utilisation de en lecture seule nous nous assurons que le nouvel attribut ne peut pas être modifié.

Ce faisant, dans votre modèle, vous pouvez maintenant utiliser :

{{ MY_CONSTANT }}

7 votes

C'est la bonne réponse mais vous devriez ajouter static pour éviter la réaffectation dans le constructeur. Donc, cela devrait vraiment être : readonly myConstant = MY_CONSTANT; Veuillez également tenir compte des recommandations du guide de style pour la syntaxe des constantes.

22voto

Günter Zöchbauer Points 21340

La portée des liaisons de modèles Angular2 est l'instance du composant. Seul ce qui y est accessible peut être utilisé dans les liaisons.

Vous pouvez le rendre disponible comme

class MyComponent {
  myConst = CONST;
}

{{myConst}}

0 votes

Y a-t-il des inconvénients à cela ? Je pense que si I CONST est un enum et que la détection des changements est Push, il ne devrait pas y en avoir.

2 votes

@bhantol Je ne pense pas qu'il y ait d'inconvénients.

0 votes

Ce n'est pas une constante. myConst peuvent être réaffectés.

20voto

Tomas Points 632

À mon avis, il y a deux meilleures directions :

Habillage des constantes en tant que propriété interne du composant

enum.ts

export enum stateEnum {
  'DOING' = 0,
  'DONE',
  'FAILED'
}

component.ts

import { stateEnum  } from './enum'
export class EnumUserClass {
  readonly stateEnum : typeof stateEnum = stateEnum ;    
}

L'exemple utilise un enum, mais il peut s'agir de n'importe quel type de constante définie. typeof vous offre tous les avantages des fonctions de typage de TypeScript. Vous pouvez utiliser cette variable directement dans les modèles :

composant.html

<p>{{stateEnum.DOING}}<p>

Cette solution est moins efficace en termes d'utilisation de la mémoire, car elle revient à dupliquer les données (ou les références aux constantes) dans chaque composant que vous souhaitez utiliser. En outre, la syntaxe
readonly constData: typeof constData = constData
à mon avis, ils introduisent beaucoup de bruit syntaxique et peuvent être déroutants pour les nouveaux venus.

Intégration d'une constante externe dans une fonction de composant

La deuxième option consiste à envelopper votre variable/constante externe dans une fonction de composant et à utiliser cette fonction dans le modèle :

enum.ts

export enum stateEnum {
  'DOING' = 0,
  'DONE',
  'FAILED'
}

component.ts

import { stateEnum  } from './enum'
export class EnumUserClass {
  getEnumString(idx) {
    return stateEnum[stateEnum[idx]];
  }   
}

composant.html

<p>{{getEnumString(1)}}</p>  

L'avantage est que les données ne sont pas dupliquées dans le contrôleur mais d'autres inconvénients majeurs apparaissent. Selon l'équipe d'Angular, l'utilisation de fonctions dans les templates n'est pas recommandée en raison du mécanisme de détection de changement, qui est beaucoup moins efficace dans le cas de fonctions renvoyant des valeurs aux templates : la détection de changement n'a aucune idée si la valeur renvoyée par une fonction a changé, donc elle sera appelée beaucoup plus souvent que nécessaire (et en supposant que vous renvoyez const il n'est en fait nécessaire qu'une seule fois, lors du remplissage de la vue du modèle. Il se peut que votre application ne soit qu'une perte d'efficacité (si vous avez de la chance) ou qu'elle s'effondre complètement si la fonction se résout par Observable par exemple, et vous utilisez async tuyau pour s'abonner aux résultats. Vous pouvez vous référer à mon court article sur ce sujet ICI

5voto

sercanD Points 99

Vous pouvez créer un BaseComponent , c'est un endroit où vous devez créer vos instances constantes et ensuite vous pouvez créer votre FooComponent extends BaseComponent et vous pouvez utiliser vos constantes.

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