Angulaire - Utiliser des tuyaux dans les services et les composants

331

Dans AngularJS, je peux utiliser des filtres (tuyaux) à l'intérieur des services et des contrôleurs en utilisant une syntaxe similaire à ceci:

$filter('date')(myDate, 'yyyy-MM-dd');

Est-il possible d'utiliser des tuyaux dans des services / composants comme celui-ci dans Angular?

Conforme à POSIX
la source
1
pour Angular 8 Consultez ce didacticiel sur les tuyaux intégrés
Code Spy

Réponses:

660

Comme d'habitude dans Angular, vous pouvez compter sur l'injection de dépendance:

import { DatePipe } from '@angular/common';

class MyService {

  constructor(private datePipe: DatePipe) {}

  transformDate(date) {
    return this.datePipe.transform(date, 'yyyy-MM-dd');
  }
}

Ajoutez DatePipeà votre liste de fournisseurs dans votre module; si vous oubliez de le faire, vous obtiendrez une erreur no provider for DatePipe:

providers: [DatePipe,...]

Mise à jour d'Angular 6 : Angular 6 propose désormais à peu près toutes les fonctions de formatage utilisées par les canaux en public. Par exemple, vous pouvez désormais utiliser formatDatedirectement la fonction.

import { formatDate } from '@angular/common';

class MyService {

  constructor(@Inject(LOCALE_ID) private locale: string) {}

  transformDate(date) {
    return formatDate(date, 'yyyy-MM-dd', this.locale);
  }
}

Avant Angular 5 : soyez averti cependant que le DatePipes'appuyait sur l'API Intl jusqu'à la version 5, qui n'est pas prise en charge par tous les navigateurs (consultez le tableau de compatibilité ).

Si vous utilisez des versions Angular plus anciennes, vous devez ajouter le Intlpolyfill à votre projet pour éviter tout problème. Voir cette question connexe pour une réponse plus détaillée.

cexbrayat
la source
Quel serait le résultat de l'utilisation de DatePipe dans un navigateur qui ne prend pas en charge Intl? Existe-t-il un type de cale / de remplissage pour contrer le manque de soutien?
Posix conforme
Cela va malheureusement générer une erreur et casser votre application en ce moment. Il y a des problèmes ouverts sur le tracker Github, mais il semble qu'il n'y ait actuellement pas de bon polyfill ...
cexbrayat
4
Cela ne semble pas fonctionner pour les canaux personnalisés qui eux-mêmes utilisent l'injection de dépendances dans leur constructeur. Ou je me trompe?
Murray Smith
1
@JayChase est en "angular2 / common".
valter.santos.matos
5
@JayChase importer et ajouter dans les sections du fournisseur de composants: `` `import {DatePipe} from '@ angular / common'; @Component ({... providers: [..., DatePipe]}) ``
alx lark
74

Cette réponse est désormais obsolète

recommander d'utiliser l'approche DI à partir d'autres réponses au lieu de cette approche

Réponse originale:

Vous devriez pouvoir utiliser la classe directement

new DatePipe().transform(myDate, 'yyyy-MM-dd');

Par exemple

var raw = new Date(2015, 1, 12);
var formatted = new DatePipe().transform(raw, 'yyyy-MM-dd');
expect(formatted).toEqual('2015-02-12');
SnareChops
la source
2
Lors de l'utilisation du Dateconstructeur javascript , les mois sont 0basés. Il en 0va de même pour janvier et 1février. Corrigé manquanty
SnareChops
24
Au cas où cela aiderait quelqu'un d'autre, le tube de date est importé de 'angular2 / common'.
Conforme à POSIX le
1
L'extrait de code ne compile pas .... error TS2345: Argument of type 'string[]' is not assignable to parameter of type 'string'. en lignevar formatted = new DatePipe().transform(raw, ['yyyy-MM-dd']);
Paul Gorbas
10
Maintenant sorti Angular v2.0.0, et vous pouvez injecter ce tuyau. Tout d'abord, ajoutez à NgModule:, @NgModule({ providers:[DatePipe] })puis dans votre classe, importez et injectez constructor( private datePipe: DatePipe ){}
ktretyak
2
pendant ce temps, Angular2 DatePipe attend le Locale_ID comme argument constructeur. Donc, si vous essayez de l'utiliser directement, vous devrez fournir un correctif Locale_ID et, par conséquent, il ne prendra plus les applications Locale_ID. C'est pourquoi je ne recommanderais PAS de suivre cette voie.
E. Hein
17

Oui, c'est possible en utilisant un simple tuyau personnalisé. L'avantage d'utiliser un canal personnalisé est que si nous devons mettre à jour le format de date à l'avenir, nous pouvons aller mettre à jour un seul fichier.

import { Pipe, PipeTransform } from '@angular/core';
import { DatePipe } from '@angular/common';

@Pipe({
    name: 'dateFormatPipe',
})
export class dateFormatPipe implements PipeTransform {
    transform(value: string) {
       var datePipe = new DatePipe("en-US");
        value = datePipe.transform(value, 'MMM-dd-yyyy');
        return value;
    }
}

{{currentDate | dateFormatPipe }}

Vous pouvez toujours utiliser ce tuyau n'importe où, composant, services, etc.

Par exemple

export class AppComponent {
  currentDate : any;
  newDate : any;
  constructor(){
    this.currentDate = new Date().getTime();
    let dateFormatPipeFilter = new dateFormatPipe();
    this.newDate = dateFormatPipeFilter.transform(this.currentDate);
    console.log(this.newDate);
}

N'oubliez pas d'importer des dépendances.

import { Component } from '@angular/core';
import {dateFormatPipe} from './pipes'

Exemples de tuyaux personnalisés et plus d'informations

Prashobh
la source
1
Cela ne répond pas à la question de l'utilisation des tuyaux dans un composant ou un service.
conforme POSIX du
2
Je supprimerai mon downvote si vous mettez à jour votre réponse pour ne pas inclure d'informations sur la façon de créer des tuyaux. La question n'a rien à voir avec la façon de les créer.
conforme à POSIX
2
@ POSIX-compliant Comme je l'ai mentionné dans ma réponse, il peut être réutilisé et mis à jour très facilement en utilisant un canal personnalisé. Cela peut aider complètement quelqu'un d'autre. Les votes sont secondaires.
Prashobh
1
C'est un bon point, même si je pense toujours qu'il est logique d'avoir au moins la partie qui répond à cette question spécifique en premier. Suppression du vote négatif. Merci pour la réponse et la réponse.
Conforme à POSIX du
1
Pourquoi avez-vous codé en dur "en-US"? Ne devriez-vous pas injecter en quelque sorte?
Gherman
15

D'autres réponses ne fonctionnent pas en angulaire 5?

J'ai reçu une erreur car DatePipe n'est pas un fournisseur, il ne peut donc pas être injecté. Une solution consiste à le mettre en tant que fournisseur dans votre module d'application, mais ma solution préférée était de l'instancier.

Instanciez-le si nécessaire:

J'ai regardé le code source de DatePipe pour voir comment il a obtenu les paramètres régionaux: https://github.com/angular/angular/blob/5.2.5/packages/common/src/pipes/date_pipe.ts#L15-L174

Je voulais l'utiliser dans un tuyau, donc mon exemple est dans un autre tuyau:

import { Pipe, PipeTransform, Inject, LOCALE_ID } from '@angular/core';
import { DatePipe } from '@angular/common';

@Pipe({
    name: 'when',
})
export class WhenPipe implements PipeTransform {
    static today = new Date((new Date).toDateString().split(' ').slice(1).join(' '));
    datePipe: DatePipe;

    constructor(@Inject(LOCALE_ID) private locale: string) {
        this.datePipe = new DatePipe(locale);
    }
    transform(value: string | Date): string {
        if (typeof(value) === 'string')
            value = new Date(value);

        return this.datePipe.transform(value, value < WhenPipe.today ? 'MMM d': 'shortTime')
    }
}

La clé ici est d'importer Inject et LOCALE_ID à partir du noyau angulaire, puis de l'injecter pour que vous puissiez le donner au DatePipe pour l'instancier correctement.

Faire de DatePipe un fournisseur

Dans votre module d'application, vous pouvez également ajouter DatePipe à votre tableau de fournisseurs comme ceci:

import { DatePipe } from '@angular/common';

@NgModule({
    providers: [
        DatePipe
    ]
})

Maintenant, vous pouvez simplement l'injecter dans votre constructeur si nécessaire (comme dans la réponse de cexbrayat).

Résumé:

L'une ou l'autre solution a fonctionné, je ne sais pas quel angulaire considérerait le plus "correct" mais j'ai choisi de l'instancier manuellement car angulaire ne fournissait pas de datepipe en tant que fournisseur lui-même.

csga5000
la source
3
Vous pouvez également en faire un fournisseur par composant
Jimmy Kane
Merci, votre réponse est la plus exhaustive. Je suis à la recherche de ressources sur les différences entre l'instanciation du tuyau avec une nouvelle ou une dépendance l'injectant directement et l'ajoutant aux fournisseurs et je ne trouve rien. Je préfère la 2e approche, car lorsque vous newmontez le tuyau, vous devez toujours DI les paramètres régionaux. Je trouve toute la @Inject(LOCALE_ID) private locale: stringsyntaxe compliquée.
Codeepic
@codeepic Je ne dirais probablement pas qu'il y a vraiment une énorme différence. Si vous me demandez, angular aurait probablement dû en faire un fournisseur.
csga5000
9

Si vous ne voulez pas faire 'new myPipe ()' parce que vous injectez des dépendances à pipe, vous pouvez injecter dans le composant comme fournisseur et utiliser sans nouveau.

Exemple:

// In your component...

import { Component, OnInit } from '@angular/core';
import { myPipe} from './pipes';

@Component({
  selector: 'my-component',
  template: '{{ data }}',
  providers: [ myPipe ]
})
export class MyComponent() implements OnInit {
  data = 'some data';
  constructor(private myPipe: myPipe) {}

  ngOnInit() {
    this.data = this.myPipe.transform(this.data);
  }
}
Andy
la source
9

Si vous souhaitez utiliser votre tuyau personnalisé dans vos composants, vous pouvez ajouter

@Injectable({
  providedIn: 'root'
})

annotation à votre tuyau personnalisé. Ensuite, vous pouvez l'utiliser comme un service

srt
la source
est-il bon d'avoir à l' providedIn: 'root'intérieur de notre tuyau ou fourni dans un module local où le tuyau est utilisé?
Daniel.V
1
Cela dépend de l'endroit où vous utilisez le tuyau. Si vous utilisez le tuyau dans un seul module, vous pouvez sélectionner la deuxième option. Mais si vous utilisez le canal dans plusieurs modules de votre application, vous devez sélectionner la première option qui est fournie dans: 'root'
srt
5

Vous pouvez utiliser formatDate () pour formater la date dans les services ou les composants ts. syntaxe:-

formatDate(value: string | number | Date, format: string, locale: string, timezone?: string): string

importer le formatDate () à partir d'un module commun comme celui-ci,

import { formatDate } from '@angular/common';

et il suffit de l'utiliser dans la classe comme celle-ci,

formatDate(new Date(), 'MMMM dd yyyy', 'en');

Vous pouvez également utiliser les options de format prédéfinies fournies par angular comme ceci,

formatDate(new Date(), 'shortDate', 'en');

Vous pouvez voir toutes les autres options de format prédéfinies ici,

https://angular.io/api/common/DatePipe

Sksaif Uddin
la source