0
votes

I have a controller that displays data in table. I use pipes to transform displayed data in view. I am asking this question because I want to find generic way to sort and filter data after it is transformed by pipe.

Use cases:

User sees "Yes" in table which in my model is an boolean. It will be transformed to Yes/No by pipe.

User sees "Status", not as number in my model - it is transformed to text. How to sort that data correctly (sorting order by number of model will not be the same as by transformed text)

When I will filter my data - I have a list of options - so it could be compared by model value.

However If I would like to make "search by text" filter - then it will be almost the same problem as with sorting.

I need only a short example / idea how it could be solved:

  • in controller find pipe by its name, and use it to transform data (if it is possible),
  • use similar syntax in controllers to use pipes (for example item.column1 | boolean) (if it is possible)

Example:

table.component.html

<table class="table table-bordered table-striped table-hover">
    <thead>
        <tr class="text-center">
            <th style="min-width: 128px;">
                Index
            </th>

            <th style="width: 25%;">
                Column1
            </th>

            <th style="width: 25%;">
                Column2
            </th>

            <th style="width: 50%;">
                Column3
            </th>
        </tr>
    </thead>

    <tbody>
        <tr *ngFor="let item of items; let i = index">


            <td>
                {{ i }}
            </td>

            <td>
                {{ item.column1 }}
            </td>

            <td>
                {{ item.column2 | itemStatus }}
            </td>

            <td>
                {{ item.column3 | boolean }}
            </td>
        </tr>
    </tbody>
</table>

item-status.pipe.ts

@Pipe({
  name: 'itemStatus'
})
export class ItemStatusPipe implements PipeTransform {

  transform(value: number, ...args: any[]): any {
    if (value <= 5) {
      return "Registered";
    }

    if (value <= 10) {
      return "Accepted";
    }

    if (value <= 20) {
      return "In progress";
    }

    if (value <= 50) {
      return "Delivered";
    }

    return "Not Accepted";
  }

}

boolean.pipe.ts

@Pipe({
  name: 'boolean'
})
export class BooleanPipe implements PipeTransform {

  transform(value: boolean, ...args: any[]): any {
    if (value === true) {
      return "Yes";
    }

    if (value === false) {
      return "No";
    }

    return "";
  }

}

item.ts

export class Item {
  column1: string;
  column2: number;
  column3: boolean;
}

table.component.ts

  items: Item[] = [
    { column1: 'name1', column2: 5, column3: true },
    { column1: 'name2', column2: 10, column3: false },
    { column1: 'name3', column2: 15, column3: true },
    { column1: 'name4', column2: 20, column3: false },
    { column1: 'name5', column2: 25, column3: true },
    { column1: 'name6', column2: 50, column3: false }
  ];
1
Have you tried passing functions to your pipe? You could pass a comparator function and a filter function. - bhantol

1 Answers

0
votes

What @bhantol1 describes I guess would be something like:

import { Pipe } from "@angular/core";

export type sortingFunction = (array: Item[]) => Item[];

@Pipe({ name: 'testSort' })
export class Pipesorter {

    transform(value: sortingFunction, itemList: Item[]): Item[] {
        return value(itemList);
    }

}

If you want to use a callback function, but this is not really that reusable, what you need to do in addition is to create those callback functions.

To be honest I don't think I would have preferred this approach at all. I would rather go for a static method of sorts that could handle the different sortings you want. Or even better utilize observables through behaviorsubjects and have the list sorted where you want them to be sorted. If you have code that appear multiple places, then use a static method for those scenarios.