2

how do I use two pipes sequentially?

<div class="thread" *ngFor="thread of threadlist | bookmarkPipe | threadPipe"></div>

In specific my threads have a bookmark:boolean property as well as tag properties (unit,task,subtask). So what I want to achieve is that the first pipe filters all threads which are bookmarked, then apply the 2nd pipe (below)

export class ThreadPipe implements PipeTransform{

  transform(array:Thread[], [unit,task,subtask]):any{

    //See all Threads
    if(unit == 0 && task == 0 && subtask == 0){
      return array
    }
    //See selected Units only
    if(unit != 0 && task == 0 && subtask == 0){
      return array.filter(thread => {
        return thread.unit === unit;
      });
    }
    //See selected Units and Tasks
    if (unit != 0 && task != 0 && subtask == 0){
      return array.filter(thread => {
        return thread.unit === unit && thread.task === task;
      });
    }
    // See selected units, tasks, subtask
    if (unit != 0 && task != 0 && subtask != 0){
      return array.filter(thread => {
        return thread.unit === unit && thread.task === task && thread.subtask === subtask;
      });
    }
  }
}
Han Che
  • 8,239
  • 19
  • 70
  • 116

1 Answers1

3

In fact, there is nothing special to do. The second pipe will receive the value from the previous one:

data -> Pipe1 -> filtered data (#1) -> Pipe2 -> filtered data (#2)

For example, if I have an array [ 'val1', 'val2', 'val3' ] and with the following pipes:

@Pipe({
  name:'pipe1'
})
export class Pipe1 {
  transform(data) {
    return data.filter((d) => {
      return d!= 'val1';
    });
  }
}

@Pipe({
  name:'pipe2'
})
export class Pipe2 {
  transform(data) {
    return data.filter((d) => {
      return d!= 'val2';
    });
  }
}

By using the following expression in an ngFor:

#elt of data | pipe1 | pipe2

data | pipe1 will return [ 'val2', 'val3' ] and return [ 'val3' ] if we apply the pipe2 on the previous result.

See the corresponding plunkr: https://plnkr.co/edit/EpKMitR3w89fRiyGYQz7?p=preview.

Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • Hi thanks for the quick reply, so basically #elt of data | pipe1 | pipe2 | pipe3 would mean something like this? ((#elt of data | pipe1) | pipe2) | pipe 3 – Han Che Apr 06 '16 at 08:49
  • Also I've just read on angular.io that it is encouraged to do list filtering with pipes and that it should be done inside the component. However i think in this case where users only click the filter once and the pipe being called only once, it should be ok? – Han Che Apr 06 '16 at 08:52
  • I think that it's the right approach here. When you have "not pure" (stateful) pipes, it's a bit different since the pipe is called every time bindings are updated. See this Mark Rajcok's awesome answer for more details: http://stackoverflow.com/questions/34456430/ngfor-doesnt-update-data-with-pipe-in-angular2/34497504. I would be interested in the link on the angular.io website ;-) – Thierry Templier Apr 06 '16 at 08:58
  • its right at the bottom under "No FilterPipe or OrderByPipe" https://angular.io/docs/ts/latest/guide/pipes.html Cheers! And of course i meant it is "discouraged" above :) – Han Che Apr 06 '16 at 09:05
  • Thanks for the link! Yes it's for impure pipes ;-) – Thierry Templier Apr 06 '16 at 09:18