Angular - Sử dụng đường ống trong các dịch vụ và linh kiện


331

Trong AngularJS, tôi có thể sử dụng các bộ lọc (đường ống) bên trong các dịch vụ và bộ điều khiển bằng cú pháp tương tự như sau:

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

Có thể sử dụng đường ống trong các dịch vụ / thành phần như thế này trong Angular không?


1
cho Angular 8 Kiểm tra hướng dẫn này về Ống tích hợp và tùy chỉnh freakyjolly.com/angular-8-pipes-all-type-of-pipes-with-examples
Code Spy

Câu trả lời:


660

Như thường lệ trong Angular, bạn có thể dựa vào tiêm phụ thuộc:

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

class MyService {

  constructor(private datePipe: DatePipe) {}

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

Thêm vào DatePipedanh sách nhà cung cấp của bạn trong mô-đun của bạn; nếu bạn quên làm điều này, bạn sẽ gặp lỗi no provider for DatePipe:

providers: [DatePipe,...]

Cập nhật Angular 6 : Angular 6 hiện cung cấp khá nhiều chức năng định dạng được sử dụng bởi các đường ống một cách công khai. Ví dụ, bây giờ bạn có thể sử dụng formatDatechức năng trực tiếp.

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

class MyService {

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

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

Trước Angular 5 : Được cảnh báo mặc dù việc DatePipedựa vào API Intl cho đến phiên bản 5, không được tất cả các trình duyệt hỗ trợ (kiểm tra bảng tương thích ).

Nếu bạn đang sử dụng các phiên bản Angular cũ hơn, bạn nên thêm Intlpolyfill vào dự án của mình để tránh mọi vấn đề. Xem câu hỏi liên quan này để có câu trả lời chi tiết hơn.


Kết quả của việc sử dụng DatePipe trong trình duyệt không hỗ trợ Intl là gì? Có bất kỳ loại shim / ployfill có sẵn để chống lại sự thiếu hỗ trợ?
POSIX tuân thủ

Nó sẽ buồn bã ném một lỗi và phá vỡ ứng dụng của bạn ngay bây giờ. Có những vấn đề được mở trên trình theo dõi Github, nhưng có vẻ như hiện tại không có polyfill tốt ...
cexbrayat

4
Điều này dường như không hoạt động đối với các đường ống tùy chỉnh mà chính chúng sử dụng phép tiêm phụ thuộc trong hàm tạo của chúng. Hay là tôi nhầm?
Murray Smith

1
@JayChase nằm trong "angular2 / common".
valter.santos.matos

5
@JayChase nhập và thêm vào các phần của nhà cung cấp thành phần: `` `import {DatePipe} từ '@ angular / common'; @Component ({... nhà cung cấp: [..., DatePipe]}) `` `
alx lark

74

Câu trả lời này đã lỗi thời

khuyên bạn nên sử dụng phương pháp DI từ các câu trả lời khác thay vì phương pháp này

Câu trả lời gốc:

Bạn sẽ có thể sử dụng lớp trực tiếp

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

Ví dụ

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

2
Khi sử dụng hàm tạo javascript Date, tháng 0dựa trên. Vậy 0là tháng một và 1là tháng hai. Sửa lỗi mất tíchy
SnareChops 2/2/2016

24
Trong trường hợp nó giúp bất kỳ ai khác, đường ống ngày được nhập từ 'angular2 / common'.
POSIX tuân thủ

1
Đoạn mã không biên dịch .... error TS2345: Argument of type 'string[]' is not assignable to parameter of type 'string'. trực tuyếnvar formatted = new DatePipe().transform(raw, ['yyyy-MM-dd']);
Paul Gorbas

10
Bây giờ đã phát hành Angular v2.0.0, và bạn có thể tiêm ống này. Đầu tiên, thêm vào NgModule : @NgModule({ providers:[DatePipe] }), sau đó trong lớp của bạn, nhập và tiêm constructor( private datePipe: DatePipe ){}
ktretyak

2
trong khi đó Angular2 DatePipe mong đợi Locale_ID làm đối số hàm tạo. Vì vậy, nếu bạn cố gắng sử dụng trực tiếp, bạn sẽ phải cung cấp bản sửa lỗi Locale_ID và do đó, nó sẽ không lấy ứng dụng Locale_ID nữa. Đó là lý do tại sao tôi KHÔNG khuyên bạn nên đi theo cách đó.
E. Hein

17

Có, có thể bằng cách sử dụng một đường ống tùy chỉnh đơn giản. Ưu điểm của việc sử dụng đường ống tùy chỉnh là nếu chúng ta cần cập nhật định dạng ngày trong tương lai, chúng ta có thể đi và cập nhật một tệp duy nhất.

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

Bạn luôn có thể sử dụng đường ống này ở bất cứ đâu, thành phần, dịch vụ, v.v.

Ví dụ

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

Đừng quên nhập phụ thuộc.

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

Ví dụ ống tùy chỉnh và thông tin thêm


1
Điều này không trả lời câu hỏi về cách sử dụng đường ống trong một thành phần hoặc dịch vụ.
POSIX tuân thủ

2
Tôi sẽ xóa downvote của tôi nếu bạn sẽ cập nhật câu trả lời của mình để không bao gồm thông tin về cách tạo đường ống. Câu hỏi không liên quan gì đến cách tạo ra chúng.
POSIX tuân thủ

2
@ Tương thích POSIX Như tôi đã đề cập trong câu trả lời của mình, nó có thể tái sử dụng và cập nhật rất dễ dàng bằng cách sử dụng đường ống tùy chỉnh. Nó có thể giúp đầy đủ cho người khác. Phiếu bầu chỉ là thứ yếu.
Prashobh

1
Đó là một điểm công bằng mặc dù tôi vẫn nghĩ rằng ít nhất có ý nghĩa để có phần trả lời câu hỏi cụ thể này trước tiên. Bỏ phiếu bầu. Cảm ơn câu trả lời và trả lời.
POSIX tuân thủ

1
Tại sao bạn lại mã hóa "en-US"? Bạn không nên tiêm vào một cách nào đó?
Gherman

15

Câu trả lời khác không hoạt động trong góc 5?

Tôi đã gặp lỗi vì DatePipe không phải là nhà cung cấp, vì vậy nó không thể được tiêm. Một giải pháp là đặt nó làm nhà cung cấp trong mô-đun ứng dụng của bạn nhưng giải pháp ưa thích của tôi là khởi tạo nó.

Khởi tạo nó khi cần thiết:

Tôi đã xem mã nguồn của DatePipe để xem làm thế nào nó có được miền địa phương: https://github.com/angular/angular/blob/5.2.5/packages/common/src/pipes/date_pipe.ts#L15-L174

Tôi muốn sử dụng nó trong một đường ống, vì vậy ví dụ của tôi là trong một đường ống khác:

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

Chìa khóa ở đây là nhập Tiêm và LOCALE_ID từ lõi của góc, sau đó tiêm vào đó để bạn có thể đưa nó cho DatePipe để khởi tạo nó đúng cách.

Biến DatePipe thành nhà cung cấp

Trong mô-đun ứng dụng của bạn, bạn cũng có thể thêm DatePipe vào mảng nhà cung cấp của mình như thế này:

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

@NgModule({
    providers: [
        DatePipe
    ]
})

Bây giờ bạn có thể chỉ cần đưa nó vào hàm tạo của bạn khi cần (như trong câu trả lời của cexbrayat).

Tóm lược:

Dù là giải pháp hiệu quả, tôi không biết một góc nào sẽ coi là "chính xác" nhất nhưng tôi đã chọn khởi tạo nó một cách thủ công vì góc không cung cấp datepipe như chính nhà cung cấp.


2
Bạn cũng có thể biến nó thành nhà cung cấp theo từng thành phần
Jimmy Kane

Cảm ơn, câu trả lời của bạn là đầy đủ nhất. Tôi đang tìm kiếm một số tài nguyên về sự khác biệt giữa khởi tạo đường ống với người mới hoặc người phụ thuộc tiêm trực tiếp và thêm nó vào nhà cung cấp và không thể tìm thấy bất cứ điều gì. Tôi thích cách tiếp cận thứ 2, vì khi bạn newlên đường ống, bạn vẫn phải DI địa phương. Tôi thấy toàn bộ @Inject(LOCALE_ID) private locale: stringcú pháp rườm rà.
codeepic

@codeepic Có lẽ tôi sẽ không nói có một sự khác biệt rất lớn. Nếu bạn hỏi tôi, góc cạnh có lẽ nên làm cho nó một nhà cung cấp.
csga5000

9

Nếu bạn muốn sử dụng đường ống tùy chỉnh trong các thành phần của mình, bạn có thể thêm

@Injectable({
  providedIn: 'root'
})

chú thích cho ống tùy chỉnh của bạn. Sau đó, bạn có thể sử dụng nó như một dịch vụ


Có tốt không khi có providedIn: 'root'bên trong đường ống của chúng tôi hoặc được cung cấp trong một mô-đun địa phương nơi sử dụng đường ống?
Daniel.V

1
Nó phụ thuộc vào nơi bạn sử dụng đường ống. Nếu bạn chỉ sử dụng đường ống trong một mô-đun thì bạn có thể chọn tùy chọn thứ hai. Nhưng nếu bạn sử dụng đường ống trong một số mô-đun trong ứng dụng của mình, bạn nên chọn tùy chọn đầu tiên được cung cấp Trong: 'root'
srt

8

Nếu bạn không muốn làm 'myPipe ()' mới vì bạn đang tiêm phụ thuộc vào đường ống, bạn có thể tiêm vào thành phần như nhà cung cấp và sử dụng mà không cần mới.

Thí dụ:

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


5

Bạn có thể sử dụng formatDate () để định dạng ngày trong các dịch vụ hoặc thành phần ts. cú pháp: -

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

nhập formatDate () từ mô-đun phổ biến như thế này,

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

và chỉ sử dụng nó trong lớp như thế này,

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

Bạn cũng có thể sử dụng các tùy chọn định dạng được xác định trước được cung cấp bởi góc như thế này,

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

Bạn có thể thấy tất cả các tùy chọn định dạng được xác định trước khác ở đây,

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.