Angular: use tuberías en servicios y componentes


331

En AngularJS, puedo usar filtros (tuberías) dentro de servicios y controladores usando una sintaxis similar a esta:

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

¿Es posible usar tuberías en servicios / componentes como este en Angular?


1
para Angular 8 Consulte este tutorial sobre Tubos integrados
Code Spy el

Respuestas:


660

Como es habitual en Angular, puede confiar en la inyección de dependencia:

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

class MyService {

  constructor(private datePipe: DatePipe) {}

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

Agregue DatePipea su lista de proveedores en su módulo; Si olvida hacer esto, recibirá un error no provider for DatePipe:

providers: [DatePipe,...]

Actualizar Angular 6 : Angular 6 ahora ofrece prácticamente todas las funciones de formato utilizadas públicamente por las canalizaciones. Por ejemplo, ahora puede usar la formatDatefunción directamente.

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

class MyService {

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

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

Antes de Angular 5 : Tenga en cuenta que DatePipeconfiaba en la API Intl hasta la versión 5, que no es compatible con todos los navegadores (consulte la tabla de compatibilidad ).

Si está utilizando versiones anteriores de Angular, debe agregar el Intlpolyfill a su proyecto para evitar cualquier problema. Consulte esta pregunta relacionada para obtener una respuesta más detallada.


¿Cuál sería el resultado de usar DatePipe en un navegador que no admite Intl? ¿Hay algún tipo de cuña / relleno disponible para contrarrestar la falta de soporte?
Compatible con POSIX

Lamentablemente arrojará un error y romperá su aplicación en este momento. Hay cuestiones abiertas en el rastreador Github, pero parece que actualmente no existe una buena polyfill ...
cexbrayat

44
Esto no parece funcionar para tuberías personalizadas que usan inyección de dependencia en su constructor. ¿O me equivoco?
Murray Smith

1
@JayChase está en "angular2 / común".
valter.santos.matos

55
@JayChase importa y agrega secciones de proveedores de componentes: `` `import {DatePipe} from '@ angular / common'; @Component ({... proveedores: [..., DatePipe]}) `` `
alx lark

74

Esta respuesta ahora está desactualizada

recomiendo usar el enfoque DI de otras respuestas en lugar de este enfoque

Respuesta original:

Deberías poder usar la clase directamente

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

Por ejemplo

var raw = new Date(2015, 1, 12);
var formatted = new DatePipe().transform(raw, 'yyyy-MM-dd');
expect(formatted).toEqual('2015-02-12');

2
Cuando se usa el Dateconstructor javascript , se 0basan los meses . Así 0es enero y 1es febrero. Falta corregiday
SnareChops del

24
En caso de que ayude a alguien más, la tubería de fecha se importa desde 'angular2 / common'.
Compatible con POSIX

1
El fragmento de código no se compila ... error TS2345: Argument of type 'string[]' is not assignable to parameter of type 'string'. en líneavar formatted = new DatePipe().transform(raw, ['yyyy-MM-dd']);
Paul Gorbas

10
Ahora lanzó Angular v2.0.0, y puede inyectar esta tubería. Primero, agregue a NgModule:, @NgModule({ providers:[DatePipe] })luego en su clase, importe e inyecte constructor( private datePipe: DatePipe ){}
ktretyak

2
mientras tanto, Angular2 DatePipe espera Locale_ID como argumento del constructor. Entonces, si intentas usarlo directamente, deberías proporcionar una solución Locale_ID y, por lo tanto, ya no tomará las aplicaciones Locale_ID. Por eso NO recomendaría ir por ese camino.
E. Hein

17

Sí, es posible mediante el uso de una tubería personalizada simple. La ventaja de usar una tubería personalizada es que si necesitamos actualizar el formato de fecha en el futuro, podemos ir y actualizar un solo archivo.

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 }}

Siempre puede usar esta tubería en cualquier lugar, componente, servicios, etc.

Por ejemplo

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);
}

No olvides importar dependencias.

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

Ejemplos de tuberías personalizadas y más información


1
Esto no responde a la pregunta de cómo usar tuberías en un componente o servicio.
Compatible con POSIX el

2
Eliminaré mi voto negativo si actualiza su respuesta para no incluir información sobre cómo crear tuberías. La pregunta no tiene nada que ver con cómo crearlos.
Compatible con POSIX el

2
@ Compatible con POSIX Como mencioné en mi respuesta, puede reutilizarse y actualizarse muy fácilmente utilizando una tubería personalizada. Puede ayudar a alguien más. Los votos son secundarios.
Prashobh

1
Ese es un punto justo, aunque todavía creo que tiene sentido al menos tener la parte que responda primero a esta pregunta específica. Eliminando el voto negativo. Gracias por la respuesta y por responder.
Compatible con POSIX el

1
¿Por qué codificaste "en-US"? ¿No deberías inyectarte de alguna manera?
Gherman

15

¿Otras respuestas no funcionan en angular 5?

Recibí un error porque DatePipe no es un proveedor, por lo que no se puede inyectar. Una solución es incluirlo como proveedor en el módulo de su aplicación, pero mi solución preferida era crear una instancia.

Instalarlo donde sea necesario:

Miré el código fuente de DatePipe para ver cómo obtuvo la configuración regional: https://github.com/angular/angular/blob/5.2.5/packages/common/src/pipes/date_pipe.ts#L15-L174

Quería usarlo dentro de una tubería, así que mi ejemplo está dentro de otra tubería:

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 clave aquí es importar Inject y LOCALE_ID desde el núcleo de angular, y luego inyectarlo para que pueda dárselo a DatePipe para crear una instancia adecuada.

Hacer de DatePipe un proveedor

En el módulo de su aplicación, también podría agregar DatePipe a su matriz de proveedores de esta manera:

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

@NgModule({
    providers: [
        DatePipe
    ]
})

Ahora puede inyectarlo en su constructor donde sea necesario (como en la respuesta de cexbrayat).

Resumen:

Cualquiera de las soluciones funcionó, no sé cuál angular consideraría más "correcto", pero elegí crear una instancia manual ya que angular no proporcionó datepipe como proveedor.


3
También puede convertirlo en un proveedor por componente
Jimmy Kane

Gracias, tu respuesta es la más exhaustiva. Estoy buscando algunos recursos sobre las diferencias entre crear instancias de la tubería con nuevas o dependencias, inyectarlas directamente y agregarlas a los proveedores y no puedo encontrar nada. Prefiero el segundo enfoque, porque cuando newsubes la tubería, todavía tienes que DI la configuración regional. Encuentro toda la @Inject(LOCALE_ID) private locale: stringsintaxis engorrosa.
codeepic

@codeepic Probablemente no diría que realmente hay una gran diferencia. Si me preguntas, angular probablemente debería haberlo hecho un proveedor.
csga5000

9

Si no desea hacer 'new myPipe ()' porque está inyectando dependencias a la tubería, puede inyectar componentes como proveedor y usar sin nuevos.

Ejemplo:

// 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);
  }
}

9

Si desea utilizar su tubería personalizada en sus componentes, puede agregar

@Injectable({
  providedIn: 'root'
})

anotación a su tubería personalizada. Entonces, puedes usarlo como un servicio


¿Es bueno tener providedIn: 'root'dentro de nuestra tubería o en un módulo local donde se usa la tubería?
Daniel.V

1
Depende de dónde use la tubería. Si usa la tubería en un solo módulo, entonces puede seleccionar la segunda opción. Pero si usa la tubería en varios módulos en su aplicación, debe seleccionar la primera opción que se proporciona en: 'root'
srt


5

Puede usar formatDate () para formatear la fecha en servicios o componentes ts. sintaxis:-

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

importa el formatDate () desde un módulo común como este,

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

y solo utilízalo en la clase como esta,

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

También puede usar las opciones de formato predefinidas proporcionadas por angular de esta manera,

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

Puede ver todas las demás opciones de formato predefinidas aquí,

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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.