เชิงมุม - ใช้ท่อในบริการและส่วนประกอบ


331

ใน AngularJS ฉันสามารถใช้ตัวกรอง (ไปป์) ภายในบริการและตัวควบคุมโดยใช้ไวยากรณ์ที่คล้ายกับสิ่งนี้:

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

เป็นไปได้ไหมที่จะใช้ท่อในบริการ / ส่วนประกอบเช่นนี้ในแองกูลาร์


1
สำหรับเชิงมุม 8 ตรวจสอบบทช่วยสอนนี้ในตัวท่อที่กำหนดเองและในตัว freakyjolly.com/angular-8-pipes-all-type-of-pipes-with-examples
รหัส Spy

คำตอบ:


660

ตามปกติใน Angular คุณสามารถพึ่งพาการฉีดพึ่งพา:

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

class MyService {

  constructor(private datePipe: DatePipe) {}

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

เพิ่มDatePipeไปยังรายชื่อผู้ให้บริการของคุณในโมดูลของคุณ; หากคุณลืมทำเช่นนี้คุณจะได้รับข้อผิดพลาดno provider for DatePipe:

providers: [DatePipe,...]

อัปเดต Angular 6 : Angular 6 ตอนนี้มีฟังก์ชั่นการจัดรูปแบบค่อนข้างมากที่ใช้โดยไพพ์สาธารณะ ตัวอย่างเช่นตอนนี้คุณสามารถใช้formatDateฟังก์ชันได้โดยตรง

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

class MyService {

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

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

ก่อน Angular 5 : ได้รับการเตือนแม้ว่าจะDatePipeใช้กับ Intl API จนถึงรุ่น 5 ซึ่งเบราว์เซอร์ทั้งหมดไม่รองรับ (ตรวจสอบตารางความเข้ากันได้ )

หากคุณใช้แองกูลาร์เวอร์ชันเก่าคุณควรเพิ่มIntlpolyfill ในโครงการของคุณเพื่อหลีกเลี่ยงปัญหาใด ๆ ดูคำถามที่เกี่ยวข้องนี้สำหรับคำตอบโดยละเอียดเพิ่มเติม


ผลลัพธ์ของการใช้ DatePipe ในเบราว์เซอร์ที่ไม่รองรับ Intl คืออะไร มี shim / ployfill ประเภทใดบ้างที่สามารถตอบโต้การขาดการสนับสนุน?
เป็นไปตาม POSIX

มันน่าเศร้าที่จะเกิดข้อผิดพลาดและทำให้แอปของคุณพังทันที มีปัญหาที่เปิดในตัวติดตาม Github แต่ดูเหมือนว่าขณะนี้ไม่มีโพลีฟิลที่ดี ...
cexbrayat

4
ดูเหมือนว่าจะไม่ทำงานสำหรับท่อแบบกำหนดเองซึ่งตัวเองใช้การฉีดแบบพึ่งพาในตัวสร้าง หรือฉันเข้าใจผิด?
Murray Smith

1
@JayChase อยู่ใน "angular2 / common"
valter.santos.matos

5
@JayChase นำเข้าและเพิ่มในส่วนผู้ให้บริการส่วนประกอบ: `` `import {DatePipe} จาก '@ angular / common'; @Component ({... ผู้ให้บริการ: [... , DatePipe]}) `` `
alx lark

74

คำตอบนี้ล้าสมัยแล้ว

แนะนำให้ใช้วิธี DI จากคำตอบอื่นแทนวิธีนี้

คำตอบเดิม:

คุณควรใช้คลาสได้โดยตรง

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

ตัวอย่างเช่น

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

2
เมื่อใช้Dateงานตัวสร้างจาวาสคริปต์จะ0ใช้เวลาหลายเดือน ดังนั้น0มกราคมและ1กุมภาพันธ์ แก้ไขการขาดหายไปy
SnareChops

24
ในกรณีที่ช่วยคนอื่นไพพ์วันที่จะถูกนำเข้าจาก 'angular2 / common'
เป็นไปตามมาตรฐาน POSIX

1
ข้อมูลโค้ดไม่ได้รวบรวม .... error TS2345: Argument of type 'string[]' is not assignable to parameter of type 'string'. ที่บรรทัดvar formatted = new DatePipe().transform(raw, ['yyyy-MM-dd']);
Paul Gorbas

10
ตอนนี้ปล่อย Angular v2.0.0 และคุณสามารถฉีดไปป์นี้ได้ ก่อนอื่นเพิ่มไปยัง NgModule: @NgModule({ providers:[DatePipe] })จากนั้นในชั้นเรียนของคุณนำเข้าและฉีด constructor( private datePipe: DatePipe ){}
ktretyak

2
ในขณะเดียวกัน Angular2 DatePipe คาดว่า Locale_ID เป็นอาร์กิวเมนต์ตัวสร้าง ดังนั้นหากคุณพยายามที่จะใช้งานโดยตรงคุณจะต้องให้การแก้ไข Locale_ID และมันจะไม่ใช้แอป Locale_ID อีกต่อไป นั่นเป็นเหตุผลที่ฉันจะไม่แนะนำให้ไปทางนั้น
E. Hein

17

ใช่เป็นไปได้โดยใช้ไพพ์แบบกำหนดเองอย่างง่าย ข้อดีของการใช้ไพพ์แบบกำหนดเองคือถ้าเราต้องการอัปเดตรูปแบบวันที่ในอนาคตเราสามารถไปและอัปเดตไฟล์เดียว

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

คุณสามารถใช้ไปป์นี้ได้ทุกที่ส่วนประกอบบริการ ฯลฯ

ตัวอย่างเช่น

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

อย่าลืมที่จะนำเข้าการอ้างอิง

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

ตัวอย่าง Pipe แบบกำหนดเองและข้อมูลเพิ่มเติม


1
สิ่งนี้ไม่ได้ตอบคำถามของวิธีการใช้ไพพ์ในส่วนประกอบหรือบริการ
เป็นไปตามมาตรฐาน POSIX

2
ฉันจะลบ downvote ของฉันถ้าคุณจะอัปเดตคำตอบของคุณเพื่อไม่รวมข้อมูลเกี่ยวกับวิธีการสร้างไปป์ คำถามไม่มีส่วนเกี่ยวข้องกับวิธีการสร้าง
เป็นไปตามมาตรฐาน POSIX

2
@ สอดคล้องกับ POSIX ดังที่ฉันได้กล่าวไว้ในคำตอบของฉันมันสามารถนำมาใช้ใหม่และอัปเดตได้ง่ายมากโดยใช้ไพพ์แบบกำหนดเอง มันอาจช่วยให้คนอื่นเต็ม โหวตเป็นรอง
Prashobh

1
นั่นเป็นประเด็นที่ยุติธรรมแม้ว่าฉันยังคิดว่าอย่างน้อยก็ควรมีส่วนที่ตอบคำถามเฉพาะนี้ก่อน การลบการลงคะแนน ขอบคุณสำหรับคำตอบและการตอบกลับ
เป็นไปตามมาตรฐาน POSIX

1
ทำไมคุณ hardcode "en-US" คุณไม่ควรฉีดอย่างใด?
Gherman

15

คำตอบอื่น ๆ ไม่ทำงานในเชิงมุม 5?

ฉันพบข้อผิดพลาดเนื่องจาก DatePipe ไม่ใช่ผู้ให้บริการดังนั้นจึงไม่สามารถฉีดได้ ทางออกหนึ่งคือการวางไว้ในฐานะผู้ให้บริการในโมดูลแอพของคุณ แต่โซลูชันที่ฉันต้องการคือการยกตัวอย่าง

ยกตัวอย่างเมื่อจำเป็น:

ฉันดูที่ซอร์สโค้ดของ DatePipe เพื่อดูว่ามีโลแคลนี้อย่างไร: https://github.com/angular/angular/blob/5.2.5/packages/common/src/pipes/date_pipe.ts#L15-L174

ฉันต้องการใช้ภายในท่อดังนั้นตัวอย่างของฉันจึงอยู่ในท่ออื่น:

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

กุญแจสำคัญในที่นี้คือการนำเข้า Inject และ LOCALE_ID จากแกนของเชิงมุมแล้วทำการฉีดเพื่อให้คุณสามารถให้ DatePipe เพื่ออินสแตนซ์ของมันอย่างถูกต้อง

ทำให้ DatePipe เป็นผู้ให้บริการ

ในโมดูลแอปของคุณคุณสามารถเพิ่ม DatePipe ในอาร์เรย์ผู้ให้บริการของคุณเช่นนี้:

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

@NgModule({
    providers: [
        DatePipe
    ]
})

ตอนนี้คุณสามารถฉีดเข้าไปใน Constructor ของคุณได้ตามต้องการ (เช่นในคำตอบของ cexbrayat)

สรุป:

วิธีแก้ปัญหาทั้งสองทำงานฉันไม่ทราบว่ามุมใดมุมหนึ่งที่จะพิจารณาว่า "ถูกต้อง" ส่วนใหญ่ แต่ฉันเลือกที่จะสร้างอินสแตนซ์ด้วยตนเองเนื่องจากมุมไม่ได้ให้ Datepipe เป็นผู้ให้บริการเอง


3
คุณสามารถทำให้เป็นผู้ให้บริการส่วนประกอบต่อ
Jimmy Kane

ขอบคุณคำตอบของคุณสมบูรณ์ที่สุด ฉันกำลังมองหาทรัพยากรบางอย่างเกี่ยวกับความแตกต่างระหว่างการสร้างอินสแตนซ์ของท่อกับการพึ่งพาใหม่หรือการฉีดโดยตรงและเพิ่มไปยังผู้ให้บริการและไม่สามารถหาอะไรได้ ฉันชอบวิธีที่ 2 ทำให้เกิดnewขึ้นเมื่อคุณเพิ่มท่อคุณยังต้อง DI ตำแหน่งที่ตั้ง ฉันพบว่า@Inject(LOCALE_ID) private locale: stringไวยากรณ์ยุ่งยากทั้งหมด
codeepic

@Codeepic ฉันอาจจะไม่พูดว่ามีความแตกต่างอย่างมากจริงๆ หากคุณถามฉันเชิงมุมอาจจะทำให้ผู้ให้บริการ
csga5000

9

หากคุณไม่ต้องการทำ 'new myPipe ()' เพราะคุณต้องการฉีดไปป์ไลน์คุณสามารถฉีดส่วนประกอบเช่นผู้ให้บริการและใช้งานได้โดยไม่ต้องมีอะไรใหม่

ตัวอย่าง:

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

หากคุณต้องการใช้ไปป์ที่กำหนดเองในส่วนประกอบของคุณคุณสามารถเพิ่ม

@Injectable({
  providedIn: 'root'
})

บันทึกย่อไปยังไปป์ที่คุณกำหนดเอง จากนั้นคุณสามารถใช้เป็นบริการ


เป็นสิ่งที่ดีที่มีprovidedIn: 'root'อยู่ในท่อของเราหรือให้ไว้ในโมดูลในพื้นที่ที่ใช้ท่อ?
Daniel.V

1
ขึ้นอยู่กับว่าคุณใช้ท่อที่ไหน ถ้าคุณใช้ไปป์ในโมดูลเดียวเท่านั้นจากนั้นคุณสามารถเลือกตัวเลือกที่สอง แต่ถ้าคุณใช้
srt

8

ตั้งแต่ Angular 6 คุณสามารถนำเข้าformatDateจาก@angular/commonยูทิลิตี้เพื่อใช้ภายในส่วนประกอบ

มันถูกบุกรุกที่https://github.com/smdunn/angular/commit/3adeb0d96344c15201f7f1a0fae7e533a408e4ae

ฉันสามารถใช้เป็น:

import {formatDate} from '@angular/common';
formatDate(new Date(), 'd MMM yy HH:mm', 'en');

แม้ว่าสถานที่จะต้องมีการจัด


5

คุณสามารถใช้ formatDate () เพื่อจัดรูปแบบวันที่ในบริการหรือส่วนประกอบ ts ไวยากรณ์: -

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

นำเข้า formatDate () จากโมดูลทั่วไปเช่นนี้

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

และใช้ในชั้นเรียนเช่นนี้

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

คุณยังสามารถใช้ตัวเลือกรูปแบบที่กำหนดไว้ล่วงหน้าที่ให้บริการโดยเชิงมุมเช่นนี้

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

คุณสามารถดูตัวเลือกรูปแบบที่กำหนดไว้ล่วงหน้าอื่น ๆ ได้ที่นี่

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.