2
votes

This is what I'm working on right now. I have a datatable with some options to filter his content:

Animated GIF

The HTML component:

<div class="row topbuffer-20">
  <div class="col">
    <h3>Thief: The Dark Project</h3>
    <p>There are <span *ngIf="fanmissions"><strong>{{fanmissions.length}}</strong></span> available Fan Missions. The last released is <strong>Veniam in Sunt Pariatur</strong> and the last updated is <strong>Ullamco Ad in Elit</strong>.</p>
  </div>
</div>
<div class="row">
  <div class="col">
    <form>
      <div class="input-group">
        <span class="input-group-addon"><i class="fa fa-search fa-fw"></i></span>
        <input class="form-control" [(ngModel)]="searchinput" name="searchinput" placeholder="Search a Fan Mission..." type="text">
      </div>
    </form>
  </div>
  <div class="col">
    <div class="btn-group">
      <span class="btn-group-addon"><i class="fa fa-filter fa-fw"></i></span>
      <button type="button" class="btn btn-secondary" data-game-short="tdp">Thief: The Dark Project</button>
      <button type="button" class="btn btn-secondary" data-game-short="tg">Thief Gold</button>
      <button type="button" class="btn btn-secondary" data-game-short="tma">Thief II: The Metal Age</button>
    </div>
  </div>
</div>
<div class="row topbuffer-20">
  <div class="col">
    <table class="table table-hover table-bordered table-sm">
      <thead class="thead-default">
        <tr>
          <th class="align-middle text-center">#</th>
          <th class="align-middle">Fan Mission</th>
          <th class="align-middle text-center">Game</th>
          <th class="align-middle text-center">Version</th>
          <th class="align-middle text-center">NewDark</th>
          <th class="align-middle text-center">First release</th>
          <th class="align-middle text-center">Last update</th>
        </tr>
      </thead>
      <tbody>
        <tr class="ectm-listedfanmission" *ngFor="let fanmission of fanmissions | EctmOrderFMsBy: 'name' | EctmFilterFMsBySearch: searchinput; let i = index">
          <td class="align-middle text-center" scope="row">{{fanmission.index}}</td>
          <th class="align-middle text-capitalize">
            <small>{{fanmission.details.author.join(', ')}}</small><br>
            {{fanmission.name}}
          </th>
          <td class="align-middle text-center" title="{{fanmission.details.game.name}}"><small>{{fanmission.details.game.short}}</small></td>
          <td class="align-middle text-center"><small>{{fanmission.details.version}}</small></td>
          <td class="align-middle text-center" *ngIf="fanmission.details.isNewdark; else newdarknotrequired"><i class="fa fa-check text-success"></i></td>
          <ng-template #newdarknotrequired><td class="align-middle text-center"><i class="fa fa-times text-danger"></i></td></ng-template>
          <td class="align-middle text-center"><small>{{fanmission.details.firstreleasedate | date:'yyyy/MM/dd'}}</small></td>
          <td class="align-middle text-center"><small>{{fanmission.details.lastupdatedate | date:'yyyy/MM/dd'}}</small></td>
        </tr>
      </tbody>
    </table>
  </div>
</div>

What I have to do:

  1. Filter items writing a value in the search input. The filter has to be able to filter by ID (fanmission.index):number, Name (fanmission.name):string, Author (fanmission.details.author):string[], Game abbr (fanmission.details.game.short):string, Game fullname (fanmission.details.game.name):string, Version (fanmission.details.version):string, First release date (fanmission.details.firstreleasedate):Date and Last release date (fanmission.details.lastupdatedate):Date.
  2. Filter items clicking on one of the three filter options. Thief: The Dark Project ("fanmission.details.game.short": "tdp"); Thief Gold ("fanmission.details.game.short": "tg") and Thief II: The Metal Age ("fanmission.details.game.short": "tma"). When I click on Thief: The Metal Age, only items which have TDP in Game column should be visible. Only ONE option can be active at once. When I click on an active option, it has to be inactive and stop to filter the datatable.
  3. Big heading at the top have to change and take the fullname of the game when one of the three filter options (buttons) is active. When I click on one of the these buttons (ex. Thief: The Dark Project), the items are filtered by game fullname and the big heading shows the game fullname (Thief: The Dark Project).
  4. The paragraph below the big heading (game/filter title) have to be updated when using filter options. When I don't use any filter, the paragraph has to return the total amount of items in my database, the last published (this one which has the most recent date) and the last updated (this one which has the most last update date). When I search an item (search input), the amount of available itmes have to be present in this paragraph. The latest updated and the first item visible also have to be indicated in the paragraph with his respective name.
  5. Each table head order the datatable content ASC/DESC. When I click on one of the the head columns, this one has to order the items present in the database ASC/DESC.
  6. When there is no result searching by specific word (search input) the table has to indicate : No result found.

I need to create custom Pipes and apply them to my ectm-list.component.

Please, consider to see my project on GitHub in order to have an idea how it is structured: http://www.github.com/jonathanlinat/enhanced-cheapthiefmissions/

Can someone help me to achieve this big task?


1. Filter items writing a value in the search input

At this moment, I can only filter by NAME. This is my Pipe:

@Pipe({
  name: 'EctmFilterFMsBySearch'
})
export class EctmFilterFMsBySearchPipe implements PipeTransform {

  transform(value: any, arg: any): any {
    if (value != null && arg != null) {
      var filteredfanmissions = value.filter((fanmission) => fanmission.name.search(new RegExp(arg, "i")) >= 0);
      if (filteredfanmissions != 0) {
        return filteredfanmissions;
      }
    } else {
      return value;
    }
  }

}

As you can see here...

value.filter((fanmission) => fanmission.name.search(new RegExp(arg, "i")) >= 0);

...I need to change fanmission.name by applying the listed ones at the top of my post. How can I achieve that? Do I need to use a loop?

1
Start by reading this: angular.io/docs/ts/latest/guide/pipes.html#!#no-filter-pipe. Then consider not using pipes to implement this.JB Nizet
@JB Ok.. so, what do I have to do exactly if I can't use pipes? Can you give me a concrete example how to achieve what I'm looking for? I watch many Angular tutorials on Youtube and devs use this kind of approach to filter content.Jonathan
You could use a service oriented structure, updated url: angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipeGuntram

1 Answers

2
votes

I faced the same scenario in developing one of my application, i dont prefer using filter as a pipe. Rather you can use it as a service and pass in the column name and the input text as a variables to the function. Then you can return fanmission."column name i.e name/id".search(new RegExp(arg, "i")) >= 0)