Manipulating template bindings with Pipes

So, we saw how we can use directives to render content depending on the data that our component classes manage, but there is another powerful feature that we will be using thoroughly in our daily practice with Angular. We are talking about Pipes.

Pipes allow us to filter and funnel the outcome of our expressions on a view level to transform or just better display the data we are binding. Their syntax is pretty simple, basically consisting of the pipe name following the expression that we want to transform, separated by a pipe symbol (hence the name):

@Component({
  selector: "greeting",
  template: "HELLO {{ name | uppercase }}"
})
class GreetingComponent {
  name: string;
}

In the preceding example, we are displaying an uppercase greeting on the screen. Since we do not know whether the name will be in uppercase or not, we ensure a consistent output by transforming the value of the name whenever it is not an uppercase version at the view level. Pipes are chainable, and Angular has a wide range of pipe types already baked in. As we will see further in this chapter, we can also build our own pipes to fine-grain data output in cases where the built-in pipes are simply not enough.

The uppercase/lowercase pipe

The name uppercase/lowercase pipe says it all. As in the example provided previously, this pipe sets the string output in uppercase or lowercase. Insert the following code anywhere in your view and check out the output for yourself:

<p>{{ 'hello world' | uppercase }}</p>
<!-- outputs 'HELLO WORLD' -->
<p>{{ 'wEIrD hElLo' | lowercase }}</p>
<!-- output is 'weird hello' -->

The number, percent, and currency pipes

Numeric data can come in a wide range of flavors, and this pipe is especially convenient when it comes to better formatting and localizing the output. These pipes use the Internationalization API, and therefore they are reliable in Chrome and Opera browsers only.

The number pipe

The number pipe will help us define the grouping and sizing of numbers using the active locale in our browser. Its format is as follows:

expression | number[:digitInfo]

Here, expression is a number and digitInfo has the following format:

{minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}

Each binding would correspond to the following:

  • minIntegerDigits: The minimum number of integer digits to use. It defaults to 1.
  • minFractionDigits: The minimum number of digits after the fraction. It defaults to 0.
  • maxFractionDigits: The maximum number of digits after the fraction. It defaults to 3.

Note

Keep in mind that the acceptable range for each of these numbers and other details will depend on your native internationalization implementation.

The percent pipe

The percent pipe formats a number as local percent. Other than this, it inherits from the Number pipe so that we can further format the output to provide a better integer and decimal sizing and grouping. Its syntax is as follows:

expression | percent[:digitInfo]

The currency pipe

Formats a number as a local currency, providing support for selecting the currency code such as USD for the US dollar or EUR for the euro and setting up how we want the currency info to be displayed. Its syntax is as follows:

expression | currency[:currencyCode[:symbolDisplay[:digitInfo]]]

In the preceding statement, currencyCode is obviously the ISO 4217 currency code, while symbolDisplay is a Boolean that indicates whether to use the currency symbol (for example, $) or the currency code (for, example USD) in the output. The default for this value is false. Similar to the number and percent pipes, we can format the output to provide a better integer and decimal sizing and grouping through the digitInfo value:

<p>{{ 11256.569 | currency:"GBP":true:'4.1-2' }}</p> 
<!-- output is '£11,256.57' -->

The slice pipe

The purpose of this pipe is equivalent to the role played by Array.prototype.slice() and String.prototype.slice()when it comes to subtracting a subset (slice) of a collection list, array, or string, respectively. Its syntax is pretty straightforward and follows the same conventions as those of the aforementioned slice() methods:

expression | slice:start[:end]

Basically, we configure a starting index where we will begin slicing either the items array or the string on an optional end index, which will fall back to the last index on the input when omitted.

Note

Both start and end arguments can take positive and negative values, as the JavaScript slice() methods do. Refer to the JavaScript API documentation for a full rundown on all the available scenarios.

Last but not least, please note that when operating on a collection, the returned list is always a copy—even when all elements are being returned.

The date pipe

You must have already guessed that the Date pipe formats a date value as a string based on the requested format. The time zone of the formatted output will be the local system time zone of the end user's machine. Its syntax is pretty simple:

expression | date[:format]

The expression input must be a date object or a number (milliseconds since the UTC epoch). The format argument is highly customizable and accepts a wide range of variations based on date-time symbols. For our convenience, some aliases have been made available as shortcuts to the most common date formats:

  • 'medium': This is equivalent to 'yMMMdjms' (for example, Sep 3, 2010, 12:05:08 PM for en-US)
  • 'short': This is equivalent to 'yMdjm' (for example, 9/3/2010, 12:05 PM for en-US)
  • 'fullDate': This is equivalent to 'yMMMMEEEEd' (for example, Friday, September 3, 2010 for en-US)
  • 'longDate': This is equivalent to 'yMMMMd' (for example, September 3, 2010)
  • 'mediumDate': This is equivalent to 'yMMMd' (for example, Sep 3, 2010 for en-US)
  • 'shortDate': This is equivalent to 'yMd' (for example, 9/3/2010 for en-US)
  • 'mediumTime': This is equivalent to 'jms' (for example, 12:05:08 PM for en-US)
  • 'shortTime': This is equivalent to 'jm' (for example, 12:05 PM for en-US)

The JSON pipe

JSON is probably the most straightforward pipe in its definition; it basically takes an object as an input and outputs it in JSON format:

{{ { name: 'Eve', age: 43 } | json }} 

Here is the output:

{ "name": "Eve", "age": 43 }

The replace pipe

The replace pipe operates pretty much like the String.prototype.replace() function of the JavaScript API, and it will evaluate a string expression, or a number that will be treated as a string either way, against a given pattern. All matches found will be then replaced by a given string replacement. We can also introduce a function, or a reference to a function, that will receive the match string found. The overall syntax is as follows:

expression | replace:pattern:replacement

It is important to note that the pattern can be configured as a regular expression. In fact, Angular 2 uses regular expressions under the hood to find string matches so make sure you escape any special character like parentheses, brackets, and so on.

The i18n pipes

As part of Angular's strong commitment to providing a strong internationalization toolset, a reduced set of pipes targeting common i18n use cases have been made available. This book will only cover the two major ones, but it is quite likely that more pipes will be released in the future. Please refer to the official documentation for further information after finishing this chapter.

The i18nPlural pipe

The i18nPlural pipe has a simple usage, where we just evaluate a numeric value against an object mapping different string values to be returned depending on the result of the evaluation. This way, we can render different strings on our template depending if the numeric value is zero, one, two, more than N, and so on. Talking about pomodoros, we could slide this in our template:

<h1> {{ pomodoros | i18nPlural:pomodorosWarningMapping }} </h1>

Then, we can have this mapping as a field of our component controller class:

class MyPomodorosComponent {
  pomodoros: number;
  pomodorosWarningMapping: any = {
    '=0': 'No pomodoros for today',
    '=1': 'One pomodoro pending',
    'other': '# pomodoros pending'
  }
}

We even bind the numeric value evaluated in the expression by introducing the '#' placeholder in the string mappings. When no matching value is found, the pipe will fall back to the mapping set with the key 'other'.

The i18nSelect pipe

The i18nSelect pipe is similar to i18nPlural pipe, but evaluates a string value instead. This pipe is perfect for localizing text interpolations or providing distinct labels depending on state changes, for instance. For example, we could recap on our pomodoro timer and serve the UI in different languages:

<button (click)="togglePause()">
  {{ languageCode | i18nSelect: localizedLabelsMap }}
</button>

In our controller class, we can populate localizedLabelsMap as follows:

class PomodoroTimerComponent {
  languageCode: string = 'fr';
  localizedLabelsMap: any = {
    'en': 'Start timer',
    'es': 'Comenzar temporizador',
    'fr': 'Démarrer une séquence',
    'other': 'Start timer'
  }
  ...
}

It is important to note that we can put this convenient pipe to use in use cases other than localising components, but to provide string bindings depending on map keys and the like. Same as the i18nPlural pipe, when no matching value is found, the pipe will fall back to the mapping set with the key 'other'.

The async pipe

Sometimes, we manage observable data or only data that is handled asynchronously by our component class, and we need to ensure that our views promptly reflect the changes in the information once the observable field changes or asynchronous loading has been accomplished after the view has been rendered. The async pipe subscribes to an observable or promise and returns the latest value it has emitted. When a new value is emitted, the async pipe marks the component to be checked for changes.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.229.86