برنامه نویسی ۸۶۳ بازدید

pipe روشی برای نوشتن تبدیل‌های مقدار نمایشی است که می‌توان در HTML اعلان کرد. Pipe داده‌ها را به عنوان ورودی می‌گیرد و آن را به یک خروجی مطلوب تبدیل می‌کند. در این مقاله به توضیح pipe در انگولار می‌پردازیم.

تعریف pipe-های انگولار کاملاً سرراست است و می‌تواند کاملاً مفید نیز باشد. انگولار برخی pipe-های داخلی مفید دارد که آماده استفاده هستند و به ما امکان می‌دهند pipe-های سفارشی خود را بسازیم. در ادامه این مقاله با طرز انجام این کار آشنا می‌شویم.

Pipe-های داخلی

همان طور که اشاره کردیم انگولار برخی pipe-های داخلی دارد که آماده استفاده در هر قالبی هستند. در این بخش قصد داریم برخی از مفیدترین آن‌ها را بررسی کنیم و با روش استفاده از آن‌ها آشنا شویم. ما در این بخش انتظار داریم نه تنها از آن‌ها در اپلیکیشن‌های انگولار بهره بگیریم، بلکه با طرز کار آن‌ها نیز می‌خواهیم آشنا شویم.

DatePipe

این pipe یک مقدار تاریخ را به صورت یک رشته قالب‌بندی می‌کند. این قالب‌بندی بر مبنای پارامترهای ارائه شده انجام می‌یابد:

const value = new Date('2019-03-01');
<p>Birthdate: {{ value | date : 'dd/MM/YYYY' }}</p>
<!-- output '01/03/2019' -->
  • ورودی: یک شیء داده، عدد (میلی‌ثانیه‌های سپری‌شده از UTC epoch) یا یک رشته ISO است.
  • پارامتر: قالب تاریخ

برای مشاهده همه قالب‌بندی‌های موجود به این صفحه (+) مراجعه کنید.

PercentagePipe

این pipe یک مقدار عددی را به یک رشته درصد تبدیل می‌کند که بر اساس پارامترهای ارائه شده قالب‌بندی می‌شود:

const value = 23.1;
<p>Percentage: {{ value | percent : '3.2-2' }}</p>
<!-- output '023,10%' -->
  • ورودی: یک عدد
  • پارامترها:
    • minIntegerDigits – کمینه تعداد ارقام صحیح پیش از ممیز اعشار. مقدار پیش‌فرض 1 است.
    • minFractionDigits – کمینه تعداد ارقام پس از ممیز اعشار. مقدار پیش‌فرض 0 است.
    • maxFractionDigits – بیشینه تعداد ارقام پس از ممیز اعشار. مقدار پیش‌فرض 0 است.

SlicePipe

این pipe یک رشته را به زیررشته‌ای از آن تبدیل می‌کند یا یک آرایه را به زیرمجموعه آن تبدیل می‌کند.

const value = 'Leonardo';
<p>Nickname: {{ value | slice : 0 : 2 }}</p>
<!-- output 'Leo' -->
--------------------------------------------------
const values = ['Red', 'Blue', 'Green', 'Purple'];
<p>Colors:</p>
<ul>
  <li *ngFor="let value of values| slice : 1 : 3" >
    {{ value }}
  </li>
</ul>
<!-- output 
  <ul>
    <li>Blue</li>
    <li>Green</li>
  </ul>
-->
  • ورودی: یک آرایه یا رشته.
  • پارامترها:
    • Startnumber – اندیس آغازین زیرمجموعه بازگشتی.
    • Endnumber – انتهای زیرمجموعه بازگشتی.

حالت‌های Lowercase و Uppercase

این pipe-ها یک رشته را به حالت همه حروف کوچک یا بزرگ تبدیل می‌کنند:

const value = 'Leonardo';
<p>In Lowercase: {{ value | lowercase }}</p>
<!-- output 'leonardo' -->
<p>In Uppercase: {{ value | uppercase }}</p>
<!-- output 'LEONARDO' -->
  • ورودی: یک رشته

Pipe-های سفارشی

برخی اوقات به تبدیل خاصی نیاز داریم که pipe-های پیش‌فرض انگولار به آن منظور پاسخگو نیستند. در این حالت باید از pipe-های سفارشی انگولار استفاده کنیم که به ما امکان می‌دهند تا pipe-های سفارشی خودمان را بسازیم و برای آن‌ها ورودی، تابع تبدیل و خروجی تعریف کنیم.

ایجاد pipe سفارشی

ابتدا باید pipe خود را بسازیم. این pipe بسیار ساده است و صرفاً برای مقاصد آموزشی استفاده می‌شود. در این pipe یک پارامتر رشته ارائه می‌کنیم که به عبارت Hello الحاق می‌شود. روش کار به صورت زیر است:

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
  name: 'sayHello'
})
export class GreetingsPipe implements PipeTransform {
  public transform(name: string): string {
    return 'Hello, ' + name;
  }
}

پارامتر Name که در دکوراتور Pipe@ تعیین می‌شود، همان نام pipe است که در HTML مانند date ،lowercase ،uppercase و pipe-های دیگر که بررسی کردیم مورد استفاده قرار می‌گیرد.

تابع تبدیل جایی که کار اصلی پایپ انجام می‌شود و در آن تبدیل مطلوب روی ورودی دریافتی را تعریف می‌کنیم. در مثال فوق یک پارامتر ورودی که رشته‌ ما است را دریافت می‌کنیم. این آن مقداری است که تابع تبدیل روی آن عمل خواهد کرد. پارامتر نخست در تابع تبدیل همواره مقداری است که با آن کار می‌کنیم.

با این حال می‌توانیم پارامترهای دیگری نیز بسته به نیاز دریافت کنیم. سپس آن‌ها را در HTML عرضه می‌کنیم و می‌توانیم از آن‌ها در تابع تبدیل استفاده کنیم. در نهایت تابع تبدیل یک رشته بازگشت می‌دهد که خروجی pipe ما خواهد بود.

ثبت یک pipe سفارشی

در این بخش برای استفاده از pipe خود باید آن را ثبت کنیم. برای ثبت یک پایپ تنها کاری که باید انجام دهیم، افزودن کلاس آن به بخش declarations ماژول است. در این جا یک ماژول برای pipe ایجاد و آن را اکسپورت می‌کنیم تا در ماژول‌های دیگر نیز استفاده شود.

import { NgModule } from '@angular/core';
import { GreetingsPipe } from './greetings.pipe';
@NgModule({
   declarations: [
     GreetingsPipe
   ],
   exports: [
     GreetingsPipe
   ]
})
export class GreetingsPipeModule { }

استفاده از pipe سفارشی

زمانی که pipe ایجاد و در یک ماژول ثبت شد، می‌توانیم آن ماژول را در محل مورد نیاز ایمپورت کنیم تا از pipe استفاده کنیم.

فرض کنید یک شیء User در کامپوننت خود داریم که دارای مشخصه firstName است که یک رشته به عنوان نام کاربر است. در این حالت می‌توانیم آن را به پاراگراف HTML خود اضافه کنیم تا به صورت زیر به کاربر خود خوشامدگویی کنیم:

this.user = {
  firstName: 'Leonardo',
  ...
};
--------------------------------------------------
<div>
  <p>You are now logged in our application!</p>
  <p>{{ user.firstName | sayHello }}</p>
</div>
<!-- output
  <p>Hello, Leonardo</p>
-->

مثال‌هایی از pipe سفارشی

اکنون می‌خواهیم برخی مثال‌های واقعی‌تر از pipe-ها را بررسی کنیم که می‌توان در اپلیکیشن‌های واقعی مورد استفاده قرار دارد.

Pipe پول

ابتدا باید اشاره کنیم که انگولار دارای یک CurrencyPipe است که می‌توان از آن استفاده کرد. با این حال اگر به مقداری قالب‌بندی خاص برای خود نیاز دارید می‌توانید برای خودتان یک pipe سفارشی بسازید. فرض کنید تبدیلی مانند 105.5 > R$ 105,50 می‌خواهیم:

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
  name: 'currencyFormat'
})export class CurrencyFormat implements PipeTransform {
  public transform(
    value: number,
    currencySign: string = 'R$ ',
    chunkDelimiter: string = '.',
    decimalDelimiter: string = ','
  ): string {
    if (!value)
      return currencySign + '0' + decimalDelimiter + '00';
    const changedValue = this.addCommas(value.toFixed(2));
    const formatted = changedValue.toString().replace(
      /[,.]/g, function (val) {
        return val === ',' ? chunkDelimiter : decimalDelimiter;
      }
    );
    return currencySign + formatted;
  }
  private addCommas(nStr) {
    nStr += '';
    const x = nStr.split('.');
    let x1 = x[0];
    const x2 = x.length > 1 ? '.' + x[1] : '';
    const rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
        x1 = x1.replace(rgx, '$1' + ',' + '$2');
    }
    return x1 + x2;
  }
}

همچنان که پیشتر اشاره کردیم می‌توان به هر تعداد که لازم است پارامترهای ورودی دریافت کرد. در این پایپ نخستین پارامتر مقداری است که می‌خواهیم آن را قالب‌بندی کنیم. با این حال، در این پایپ رشته currencySign، رشته chunkDelimiter و رشته decimalDelimiter را نیز دریافت می‌کنیم. بنابراین می‌توانیم از آن‌ها در تابع تبدیل خود استفاده کنیم. طرز کار پایپ به صورت زیر است:

{{ 9999.9 | currencyFormat : 'R$' : '.' : ',' }}
<!-- output: R$ 9.999.90 -->

Pipe قالب‌بندی سند

در کشور برزیل هر فرد یک سند شناسایی به نام CPF دارد که این سند دارای یک شماره منحصر به فرد با قالب‌بندی خاص است. برخی اوقات باید یک رشته خام را دریافت کرده و سندی با قالب‌بندی صحیح بازگشت دهیم. در این حالت برای مثال تبدیلی مانند 11111111111 -> 111.111.111–11 اجرا می‌شود:

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
  name: 'cpfFormat'
})
export class CpfFormat implements PipeTransform {
  public transform(cpf: string): string {
    if (!cpf || cpf.trim() === '') { return ''; }
    let formatted: string;
    formatted = cpf.substring(0, 3) + '.';
    formatted = formatted + cpf.substring(3, 6) + '.';
    formatted = formatted + cpf.substring(6, 9) + '-';
    formatted = formatted + cpf.substring(9, 11);
    return formatted;
  }
}

در کد فوق pipe بسیار ساده‌تر است. ما به هیچ پارامتر دیگری به جز خود مقدار نیاز نداریم، زیرا قالب‌بندی یک CPF الگوی تعریف‌شده‌ای است. بدین ترتیب یک رشته CPF قالب‌بندی نشده دریافت می‌کنیم و یک رشته CPF قالب‌بندی شده بازگشت می‌دهیم. طرز استفاده از pipe نیز به صورت زیر است:

{{ '99999999999' | cpfFormat }}
<!-- output: 999.999.999-99 -->

تست کردن pipe

ایجاد تست‌های unit برای Pipe-های سفارشی کاری کاملاً ساده است، چون تابع‌های خالص محسوب می‌شوند. تابع‌های خالص یک ورودی دریافت کرده و خروجی مطلوب را ارائه می‌کنند. در ادامه مثالی از ایجاد یک تست ساده برای pipe قبلی CPF را ملاحظه می‌کنید:

import { CpfFormat } from './cpf.pipe';
describe('[Pipe] CPF Format', () => { 
  let pipe: CpfFormat;
  beforeEach(() => {
    pipe = new CpfFormat();
  }); 
  it('should return a valid \'cpf\' formatted correctly', () => {
    expect(pipe.transform('32726532950')).toBe('327.265.329-50');
  });
  it('should return empty for a null \'cpf\'', () => {
    expect(pipe.transform(null)).toBe('');
    expect(pipe.transform('')).toBe('');
  });
});

Pipe-های انگولار بسیار ساده هستند، اما کارکردی مفیدی محسوب می‌شوند که در اپلیکیشن‌های انگولار کاربرد وسیعی پیدا کرده‌اند. از این رو آشنایی با آن‌ها و روش استفاده مؤثر از آن‌ها برای رفع نیازها از اهمیت بالایی برخوردار است.

اگر این مطلب برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

بر اساس رای ۱ نفر
آیا این مطلب برای شما مفید بود؟
شما قبلا رای داده‌اید!
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.

«میثم لطفی» در رشته‌های ریاضیات کاربردی و مهندسی کامپیوتر به تحصیل پرداخته و شیفته فناوری است. وی در حال حاضر علاوه بر پیگیری علاقه‌مندی‌هایش در رشته‌های برنامه‌نویسی، کپی‌رایتینگ و محتوای چندرسانه‌ای، در زمینه نگارش مقالاتی با محوریت نرم‌افزار با مجله فرادرس همکاری دارد.

نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد.

مشاهده بیشتر