Winkel - Verwenden Sie Rohre in Diensten und Komponenten

331

In AngularJS kann ich Filter (Pipes) in Diensten und Controllern mit einer ähnlichen Syntax verwenden:

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

Ist es in Angular möglich, Rohre in solchen Diensten / Komponenten zu verwenden?

POSIX-konform
quelle
1
für Angular 8 Überprüfen Sie dieses Tutorial auf eingebauten und benutzerdefinierten Rohren freakyjolly.com/angular-8-pipes-all-type-of-pipes-with-examples
Code Spy

Antworten:

660

Wie in Angular üblich, können Sie sich auf die Abhängigkeitsinjektion verlassen:

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

class MyService {

  constructor(private datePipe: DatePipe) {}

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

Fügen Sie DatePipeIhrer Providerliste in Ihrem Modul hinzu. Wenn Sie dies vergessen, wird eine Fehlermeldung angezeigt no provider for DatePipe:

providers: [DatePipe,...]

Update Angular 6 : Angular 6 bietet jetzt so ziemlich alle Formatierungsfunktionen, die von den Pipes öffentlich verwendet werden. Beispielsweise können Sie die formatDateFunktion jetzt direkt verwenden.

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

class MyService {

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

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

Vor Angular 5 : Seien Sie jedoch gewarnt, dass Sie DatePipesich bis Version 5 auf die Intl-API verlassen haben, die nicht von allen Browsern unterstützt wird (überprüfen Sie die Kompatibilitätstabelle ).

Wenn Sie ältere Angular-Versionen verwenden, sollten Sie die IntlPolyfüllung zu Ihrem Projekt hinzufügen , um Probleme zu vermeiden. In dieser verwandten Frage finden Sie eine detailliertere Antwort.

Cexbrayat
quelle
Was wäre das Ergebnis der Verwendung von DatePipe in einem Browser, der Intl nicht unterstützt? Gibt es irgendeine Art von Unterlegscheibe / Trickfüllung, um mangelnder Unterstützung entgegenzuwirken?
POSIX-konform
Es wird leider einen Fehler auslösen und Ihre App jetzt brechen. Es gibt Probleme mit dem Github-Tracker, aber es sieht so aus, als ob es derzeit keine gute Polyfüllung gibt ...
Cexbrayat
4
Dies scheint nicht für benutzerdefinierte Pipes zu funktionieren, die selbst die Abhängigkeitsinjektion in ihrem Konstruktor verwenden. Oder irre ich mich?
Murray Smith
1
@ JayChase ist in "angle2 / common".
valter.santos.matos
5
@ JayChase importieren und in Komponentenanbieterabschnitten hinzufügen: `` `{DatePipe} aus '@ angle / common' importieren; @Component ({... Anbieter: [..., DatePipe]}) `` `
alx lark
74

Diese Antwort ist jetzt veraltet

empfehlen, anstelle dieses Ansatzes den DI-Ansatz aus anderen Antworten zu verwenden

Ursprüngliche Antwort:

Sie sollten die Klasse direkt verwenden können

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

Zum Beispiel

var raw = new Date(2015, 1, 12);
var formatted = new DatePipe().transform(raw, 'yyyy-MM-dd');
expect(formatted).toEqual('2015-02-12');
SnareChops
quelle
2
Bei Verwendung des Javascript- DateKonstruktors 0basieren Monate . So 0ist Januar und 1ist Februar. Korrigiert fehlendy
SnareChops
24
Wenn es jemand anderem hilft, wird die Datums-Pipe aus 'angle2 / common' importiert.
POSIX-konform
1
Code-Snippet wird nicht kompiliert .... error TS2345: Argument of type 'string[]' is not assignable to parameter of type 'string'. onlinevar formatted = new DatePipe().transform(raw, ['yyyy-MM-dd']);
Paul Gorbas
10
Jetzt Angular v2.0.0 veröffentlicht, und Sie können diese Pipe injizieren. Zuerst zu NgModule hinzufügen:, @NgModule({ providers:[DatePipe] })dann in Ihrer Klasse importieren und injizieren constructor( private datePipe: DatePipe ){}
ktretyak
2
In der Zwischenzeit erwartet Angular2 DatePipe die Locale_ID als Konstruktorargument. Wenn Sie also versuchen, es direkt zu verwenden, müssten Sie eine feste Locale_ID angeben, und dafür werden keine Apps Locale_ID mehr benötigt. Deshalb würde ich NICHT empfehlen, diesen Weg zu gehen.
E. Hein
17

Ja, es ist möglich, ein einfaches benutzerdefiniertes Rohr zu verwenden. Der Vorteil der Verwendung einer benutzerdefinierten Pipe besteht darin, dass wir eine einzelne Datei aktualisieren können, wenn wir das Datumsformat in Zukunft aktualisieren müssen.

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

Sie können diese Pipe jederzeit überall verwenden, Komponenten, Dienste usw.

Zum Beispiel

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

Vergessen Sie nicht, Abhängigkeiten zu importieren.

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

Beispiele für benutzerdefinierte Rohre und weitere Informationen

Prashobh
quelle
1
Dies beantwortet nicht die Frage, wie Rohre in einer Komponente oder einem Dienst verwendet werden sollen.
POSIX-konform
2
Ich werde meine Ablehnung entfernen, wenn Sie Ihre Antwort so aktualisieren, dass sie keine Informationen zum Erstellen von Pipes enthält. Die Frage hat nichts damit zu tun, wie man sie erstellt.
POSIX-konform
2
@ POSIX-kompatibel Wie ich in meiner Antwort erwähnt habe, kann es mithilfe einer benutzerdefinierten Pipe sehr einfach wiederverwendet und aktualisiert werden. Es kann jemand anderem voll helfen. Stimmen sind zweitrangig.
Prashobh
1
Das ist ein fairer Punkt, obwohl ich immer noch denke, dass es sinnvoll ist, zumindest den Teil zu haben, der diese spezielle Frage zuerst beantwortet. Abstimmung nach unten entfernen. Danke für die Antwort und die Antwort.
POSIX-konform
1
Warum haben Sie "en-US" fest codiert? Solltest du nicht irgendwie einspritzen?
Gherman
15

Andere Antworten funktionieren nicht in Winkel 5?

Ich habe eine Fehlermeldung erhalten, da DatePipe kein Anbieter ist und daher nicht injiziert werden kann. Eine Lösung besteht darin, es als Anbieter in Ihr App-Modul aufzunehmen, aber meine bevorzugte Lösung bestand darin, es zu instanziieren.

Instanziieren Sie es wo nötig:

Ich habe mir den Quellcode von DatePipe angesehen, um zu sehen, wie er zum Gebietsschema kam: https://github.com/angular/angular/blob/5.2.5/packages/common/src/pipes/date_pipe.ts#L15-L174

Ich wollte es in einer Pipe verwenden, daher befindet sich mein Beispiel in einer anderen Pipe:

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

Der Schlüssel hier ist, Inject und LOCALE_ID aus dem Winkelkern zu importieren und diese dann zu injizieren, damit Sie sie der DatePipe geben können, um sie ordnungsgemäß zu instanziieren.

Machen Sie DatePipe zu einem Anbieter

In Ihrem App-Modul können Sie DatePipe auch wie folgt zu Ihrem Provider-Array hinzufügen:

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

@NgModule({
    providers: [
        DatePipe
    ]
})

Jetzt können Sie es bei Bedarf einfach in Ihren Konstruktor injizieren lassen (wie in der Antwort von cexbrayat).

Zusammenfassung:

Beide Lösungen haben funktioniert, ich weiß nicht, welcher Winkel als am "richtigsten" angesehen wird, aber ich habe mich dafür entschieden, ihn manuell zu instanziieren, da Angular Datepipe als Anbieter selbst nicht bereitgestellt hat.

csga5000
quelle
2
Sie können es auch zu einem Anbieter pro Komponente machen
Jimmy Kane
Vielen Dank, Ihre Antwort ist die umfassendste. Ich suche nach Ressourcen zu Unterschieden zwischen dem Instanziieren der Pipe mit einer neuen oder der direkten Injizierung der Pipe und dem Hinzufügen zu Anbietern und kann nichts finden. Ich bevorzuge den 2. Ansatz, newdenn wenn Sie die Pipe hochfahren, müssen Sie immer noch das Gebietsschema ändern. Ich finde die ganze @Inject(LOCALE_ID) private locale: stringSyntax umständlich.
Codeepic
@codeepic Ich würde wahrscheinlich nicht sagen, dass es wirklich einen großen Unterschied gibt. Wenn Sie mich fragen, hätte Angular es wahrscheinlich zu einem Anbieter machen sollen.
csga5000
9

Wenn Sie Ihre benutzerdefinierte Pipe in Ihren Komponenten verwenden möchten, können Sie hinzufügen

@Injectable({
  providedIn: 'root'
})

Anmerkung zu Ihrer benutzerdefinierten Pipe. Dann können Sie es als Dienst verwenden

srt
quelle
Ist es gut, sie providedIn: 'root'in unserem Rohr zu haben oder in einem lokalen Modul bereitzustellen, in dem das Rohr verwendet wird?
Daniel.V
1
Dies hängt davon ab, wo Sie das Rohr verwenden. Wenn Sie das Rohr nur in einem Modul verwenden, können Sie die zweite Option auswählen. Wenn Sie die Pipe jedoch in mehreren Modulen Ihrer App verwenden, sollten Sie die erste Option auswählen, die bereitgestellt wird: 'root'
srt
8

Wenn Sie 'new myPipe ()' nicht ausführen möchten, weil Sie Abhängigkeiten in Pipe einfügen, können Sie Komponenten wie Provider einfügen und ohne neue verwenden.

Beispiel:

// 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
quelle
5

Mit formatDate () können Sie das Datum in Diensten oder Komponenten ts formatieren. Syntax:-

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

Importieren Sie das formatDate () aus einem allgemeinen Modul wie folgt:

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

und benutze es einfach in der Klasse so,

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

Sie können auch die vordefinierten Formatoptionen verwenden, die von angle wie folgt bereitgestellt werden:

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

Sie können alle anderen vordefinierten Formatoptionen hier sehen.

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

Sksaif Uddin
quelle