Kątowe - używaj rur w usługach i komponentach

331

W AngularJS jestem w stanie używać filtrów (potoków) wewnątrz usług i kontrolerów przy użyciu składni podobnej do tej:

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

Czy można używać rur w takich usługach / komponentach w Angular?

Zgodny z POSIX
źródło
1
dla kątowego 8 Sprawdź ten tutorial na wbudowane i niestandardowe Rury freakyjolly.com/angular-8-pipes-all-type-of-pipes-with-examples
Code Spy

Odpowiedzi:

660

Jak zwykle w Angular, możesz polegać na wstrzykiwaniu zależności:

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

class MyService {

  constructor(private datePipe: DatePipe) {}

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

Dodaj DatePipedo listy dostawców w swoim module; jeśli zapomnisz to zrobić, pojawi się błąd no provider for DatePipe:

providers: [DatePipe,...]

Aktualizacja Angular 6 : Angular 6 oferuje teraz prawie wszystkie funkcje formatowania używane publicznie przez potoki. Na przykład możesz teraz używać tej formatDatefunkcji bezpośrednio.

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

class MyService {

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

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

Przed Angularem 5 : Ostrzegam jednak, że DatePipepolegał on na Intl API aż do wersji 5, która nie jest obsługiwana przez wszystkie przeglądarki (sprawdź tabelę kompatybilności ).

Jeśli używasz starszych wersji IntlAngulara, dodaj do swojego projektu wypełnienie wieloskładnikowe, aby uniknąć problemów. Zobacz to powiązane pytanie, aby uzyskać bardziej szczegółową odpowiedź.

Cexbrayat
źródło
Jaki byłby wynik używania DatePipe w przeglądarce, która nie obsługuje Intl? Czy jest dostępny jakiś rodzaj podkładki / podkładki, aby przeciwdziałać brakowi wsparcia?
Zgodny z POSIX
Niestety, w tej chwili zgłasza błąd i psuje twoją aplikację. W trackerze Github są otwarte problemy, ale wygląda na to, że obecnie nie ma dobrej polifill ...
cexbrayat
4
Nie działa to w przypadku niestandardowych potoków, które same używają wstrzykiwania zależności w swoim konstruktorze. Czy się mylę?
Murray Smith
1
@JayChase jest w „angular2 / common”.
valter.santos.matos
5
@JayChase importuj i dodawaj sekcje dostawcy komponentów: `` import {DatePipe} z '@ angular / common'; @Component ({... dostawcy: [..., DatePipe]}) ``
alx lark
74

Ta odpowiedź jest teraz nieaktualna

zalecam stosowanie podejścia DI z innych odpowiedzi zamiast tego podejścia

Oryginalna odpowiedź:

Powinieneś mieć możliwość bezpośredniego korzystania z klasy

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

Na przykład

var raw = new Date(2015, 1, 12);
var formatted = new DatePipe().transform(raw, 'yyyy-MM-dd');
expect(formatted).toEqual('2015-02-12');
SnareChops
źródło
2
Podczas korzystania z Datekonstruktora javascript 0oparte są miesiące . Tak 0jest styczeń i 1luty. Poprawiono braky
SnareChops
24
Ponieważ pomaga to każdemu innemu, potok daty jest importowany z „angular2 / common”.
Zgodny z POSIX
1
Fragment kodu nie kompiluje się ... error TS2345: Argument of type 'string[]' is not assignable to parameter of type 'string'. w siecivar formatted = new DatePipe().transform(raw, ['yyyy-MM-dd']);
Paul Gorbas
10
Teraz wydany Angular v2.0.0, i możesz wstrzyknąć tę rurkę. Najpierw dodaj do NgModule: @NgModule({ providers:[DatePipe] })następnie w swojej klasie zaimportuj i wstrzykuj constructor( private datePipe: DatePipe ){}
ktretyak
2
tymczasem Angular2 DatePipe oczekuje Locale_ID jako argumentu konstruktora. Więc jeśli spróbujesz użyć go bezpośrednio, musisz podać poprawkę Locale_ID, a zatem nie zajmie to więcej aplikacji Locale_ID. Dlatego NIE zalecałbym pójść tą drogą.
E. Hein
17

Tak, jest to możliwe przy użyciu prostej niestandardowej potoku. Zaletą korzystania z potoku niestandardowego jest to, że jeśli będziemy musieli zaktualizować format daty w przyszłości, możemy przejść i zaktualizować pojedynczy plik.

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

Zawsze możesz używać tego potoku w dowolnym miejscu, komponencie, usługach itp

Na przykład

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

Nie zapomnij zaimportować zależności.

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

Niestandardowe przykłady rur i więcej informacji

Prashobh
źródło
1
To nie odpowiada na pytanie, jak używać rur w komponencie lub usłudze.
Zgodny z POSIX
2
Usunę moją opinię, jeśli zaktualizujesz swoją odpowiedź, aby nie zawierała informacji o tworzeniu rur. Pytanie nie ma nic wspólnego z ich tworzeniem.
Zgodny z POSIX
2
@ Zgodny z POSIX Jak wspomniałem w mojej odpowiedzi, można go bardzo łatwo używać i aktualizować za pomocą niestandardowego potoku. Może pomóc w pełni komuś innemu. Głosy są drugorzędne.
Prashobh
1
To słuszna kwestia, chociaż nadal uważam, że sensowne jest przynajmniej udzielenie odpowiedzi na to pytanie w pierwszej kolejności. Usunięcie głosu. Dziękuję za odpowiedź i odpowiedź.
Zgodny z POSIX
1
Dlaczego na stałe napisałeś „en-US”? Nie powinieneś jakoś wstrzykiwać?
Gherman
15

Inne odpowiedzi nie działają w kanciastym 5?

Wystąpił błąd, ponieważ DatePipe nie jest dostawcą, więc nie można go wstrzyknąć. Jednym z rozwiązań jest umieszczenie go jako dostawcy w module aplikacji, ale moim preferowanym rozwiązaniem było utworzenie go.

Utwórz go w razie potrzeby:

Przejrzałem kod źródłowy DatePipe, aby zobaczyć, w jaki sposób uzyskał ustawienia regionalne: https://github.com/angular/angular/blob/5.2.5/packages/common/src/pipes/date_pipe.ts#L15-L174

Chciałem użyć go w rurze, więc mój przykład znajduje się w innej rurze:

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

Kluczem tutaj jest import Inject i LOCALE_ID z rdzenia kątowego, a następnie wstrzyknięcie tego, aby można go było przekazać DatePipe w celu prawidłowego utworzenia instancji.

Ustaw DatePipe jako dostawcę

W module aplikacji możesz również dodać DatePipe do tablicy dostawców w następujący sposób:

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

@NgModule({
    providers: [
        DatePipe
    ]
})

Teraz możesz po prostu wstrzyknąć go do konstruktora tam, gdzie jest to potrzebne (jak w odpowiedzi cexbrayat).

Podsumowanie:

Oba rozwiązania działały, nie wiem, który kąt byłby uważany za najbardziej „poprawny”, ale zdecydowałem się utworzyć go ręcznie, ponieważ kątownik nie dostarczył potoku daty jako sam dostawca.

csga5000
źródło
3
Możesz ustawić go również jako dostawcę na komponent
Jimmy Kane
Dzięki, twoja odpowiedź jest najbardziej wyczerpująca. Szukam zasobów na temat różnic między tworzeniem potoku z nowym lub zależnością, wstrzykiwaniem go bezpośrednio a dodawaniem go do dostawców i nic nie mogę znaleźć. Wolę drugie podejście, ponieważ kiedy wchodzisz na newgórę rury, nadal musisz wybrać lokalizację. Uważam, że cała @Inject(LOCALE_ID) private locale: stringskładnia jest niewygodna.
codeepic
@codeepic Prawdopodobnie nie powiedziałbym, że naprawdę jest ogromna różnica. Jeśli mnie zapytasz, prawdopodobnie kątowy powinien był uczynić go dostawcą.
csga5000,
9

Jeśli nie chcesz robić „new myPipe ()”, ponieważ wstrzykujesz zależności do potoku, możesz wprowadzić komponent taki jak dostawca i używać go bez nowego.

Przykład:

// 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
źródło
9

Jeśli chcesz użyć niestandardowej rury w swoich komponentach, możesz dodać

@Injectable({
  providedIn: 'root'
})

adnotacja do potoku niestandardowego. Następnie możesz użyć go jako usługi

srt
źródło
czy dobrze jest mieć providedIn: 'root'wewnątrz naszej rury, czy być w lokalnym module, w którym używana jest rura?
Daniel.V
1
To zależy od tego, gdzie używasz rury. Jeśli używasz potoku tylko w jednym module, możesz wybrać drugą opcję. Ale jeśli używasz potoku w kilku modułach w swojej aplikacji, powinieneś wybrać pierwszą opcję, która jest dostępna w: 'root'
srt
5

Możesz użyć formatDate (), aby sformatować datę w usługach lub komponencie ts. składnia:-

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

zaimportuj formatDate () ze wspólnego modułu takiego jak ten,

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

i po prostu użyjcie go w takiej klasie,

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

Możesz również użyć predefiniowanych opcji formatu udostępnianych przez angular w ten sposób,

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

Tutaj możesz zobaczyć wszystkie inne predefiniowane opcje formatu,

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

Sksaif Uddin
źródło