HappyCoder
HappyCoder

Reputation: 6155

Angular2 Explode Pipe

I am busy writing my first pipe for Angular2 and I need some help putting this together.

The problem: I have an api returning a set of numbers: 1-2-03-4-5 and I would like to style these numbers like so:

<div class="number">1</div>
<div class="number">2</div>
<div class="number">03</div>
<div class="number">4</div>
<div class="number">5</div>

If this where PHP I wold simply go:

$array = explode("-","1-2-03-4-5");
foreach ($array AS $number) {
    echo ' <div class="number">'.$number.'</div>';
}

My aim is to do this sort of thing in angular so I have created a pipe:

import {Pipe} from "angular2/core";

@Pipe({
    name:"explode"
})
export class ExplodePipe {
    transform(value) {
        return some explody stuff here;
    }
}

This is included in my component

import {Component, OnInit} from 'angular2/core';
import {RouteParams, ROUTER_DIRECTIVES} from "angular2/router";
import {HelpMenuComponent} from "./help-menu.component";
import {ExplodePipe} from "../Pipes/my.pipes";

@Component({
    pipes:[ExplodePipe],

    template: `
        {{ExplodeMe | explode}}

    `
    ...

export class ViewResultsComponent implements OnInit { ExplodeMe: "1-2-03-4-5"; }

  1. Where would I insert the HTML to be included in the output? Would this be in the pipe method? Can I somehow tell the pipe to format in a certain way from the {{}} part?
  2. What data is made available to the pipe how do I access it?

Thanks!

Upvotes: 1

Views: 3606

Answers (2)

HappyCoder
HappyCoder

Reputation: 6155

So I thought I would post my final solution. This essentially does exactly what PHP explode does and is very useful!

My pipe:

import {Pipe} from "angular2/core";
import {InvalidPipeArgumentException} from "angular2/src/common/pipes/invalid_pipe_argument_exception";
import {isString, isBlank} from "angular2/src/facade/lang";

@Pipe({
    name:"explode"
})
export class ExplodePipe {

    transform(value, key) {

        if (!isString(key))
        {
           key = '-';
        }

        if (isBlank(value))
            return value;
        if (!isString(value)) {
            throw new InvalidPipeArgumentException(ExplodePipe, value);
        }

        return value.split(key);

    }

}

And using the pipe in my html code:

Split some string: 1-2-3-4-5

{{SomeString | explode:'-'}} or simply: {{SomeString | explode}} since '-' is default

Split some string: 1*2*3*4*5

{{SomeString | explode:'*'}}

And in a real example:

SomeNumbers = '1,2,3';
<div *ngFor="#item of SomeNumbers | explode:','" class="number">{{item}}</div>

Prints out:

<div class="number">1</div>
<div class="number">2</div>
<div class="number">3</div>

And that is exactly what I wanted :)

Upvotes: 0

Michael Kang
Michael Kang

Reputation: 52867

Pipes are used to take data as input, and to transform it as output. The implementation of the transformation function is up to you. But keep in mind that the output still needs to be data (it cannot contain HTML).

I suggest that you create a Pipe that takes a string and returns an array, using a dash as the split delimiter:

@Pipe({
    name:"explode"

})
export class ExplodePipe {
    transform(value) {
        return value.split('-');
    }
}

Use the Pipe in an *ngFor expression to loop over the items and format each item in a div:

@Component({
    selector: 'app',
    pipes: [ExplodePipe]
    template: `
        <div *ngFor="#item of test | explode ">{{item}}
        </div>
    `
})
export class AppComponent {
    test:string;
    constructor() {
      this.test = '1-2-03-4-5'
    }
}

Demo Plnkr

[Edit]

Building a Re-usable Component

If you have a common template that you want to consistently apply with the pipe, combine the pipe and template into a reusable component:

@Component({
  selector: 'explode',
  pipes: [ExplodePipe],
  template: `
        <div *ngFor="#item of data | explode ">{{item}}
        </div>
  `
})
export class ExplodeComponent {
   @Input() data:String;

}

Usage:

@Component({
    selector: 'app',
    directives: [ExplodeComponent],
    template: `
      <explode [data]="test"></explode>
    `
})
export class AppComponent {
    test:string;
    constructor() {
      this.test = '1-2-03-4-5'
    }
}

Demo Plnkr

Upvotes: 6

Related Questions