3

I see that support for datatables in angular 2 is very poor. DataTables does not work for me (known unresolved issue) so I thought that I will write something simple for myself. By the way I will learn something useful. I want to build my table in this way:

<my-table> 
    <my-table-row *ngFor="let row of rows">
         <my-table-col>{{row.col1}}</my-table-col>
         <my-table-col>{{row.col2}}</my-table-col>
    </my-table-row>
</my-table>

So I have created a component with simple filter input. Now, I would like to filter over my table. Angular should in some way assign data from my-table-col(s) to some variable (maybe 2way data binding will be useful?), then I would use some function triggered by keyup event to filter and data should update automatically but I do not know how to do that.

import { Component, Input, OnInit } from '@angular/core';
import { BrowserModule }  from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

@Component({
    selector: 'my-table',
    template: `
    <div style="width: 100%">
        <div style="float: left; height: 50px; width: 100%">
            Search: <input type="text" [(ngModel)]="filterValue" style="height: 30px; border: 1px solid silver"/> {{filterValue}}
        </div>
        <div style="float: left; width: 100%">
            <table>
                <ng-content></ng-content>
            </table>
        </div>
    </div>
    `
})
export class MyTableComponent { 
    filterValue: string;
}  

@Component({
    selector: 'my-table-row',
    template: `
        <tr><ng-content></ng-content></tr>
    `
})
export class MyTableRowComponent { 
}   

@Component({
    selector: 'my-table-col',
    template: `
        <td><ng-content></ng-content></td>
    `
})
export class MyTableColComponent { 
}   

Regards

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
Michal Bialek
  • 499
  • 1
  • 10
  • 26

2 Answers2

5

update Angular 5

ngOutletContext was renamed to ngTemplateOutletContext

See also https://github.com/angular/angular/blob/master/CHANGELOG.md#500-beta5-2017-08-29

original

For your example creating a new component for row and col seems unnecessary.

With a simple filter pipe like

@Pipe({ name: 'filter' })
export class FilterPipe implements PipeTransform {
  transform(data: any[], filter:string) {
    console.log('filter', data, filter);
    if(!data || !filter) {
      return data;
    }
    return data.filter(row => row.some(col => col && col.indexOf(filter) >= 0));
  }
}

and a table component like

@Component({
    selector: 'my-table',
    template: `
<div style="width: 100%">
  <div style="float: left; height: 50px; width: 100%">
    Search: 
    <input type="text" 
        [(ngModel)]="filterValue" 
        name="filter"
        style="height: 30px; border: 1px solid silver"/> 
      {{filterValue}}
  </div>
  <div style="float: left; width: 100%">
    <table>
      <tr *ngFor="let row of data | filter:filterValue">
        <td *ngFor="let col of row let index=index">
          <template [ngTemplateOutlet]="templates && templates[index]" [ngOutletContext]="{$implicit: col}"></template>
        </td>
      </tr>
    </table>
  </div>
</div>
    `
})
export class MyTableComponent { 
  filterValue: string;
  @ContentChildren(TemplateRef) templateRefs:QueryList<TemplateRef>;
  @Input() data:any[];
  templates:TemplateRef[];

  ngAfterContentInit() {
    this.templates = this.templateRefs.toArray();
  }
} 

it can be used like

@Component({
  selector: 'my-app',
  template: `
<my-table [data]="data">
  <template let-col>1: {{col}}</template>
  <template let-col>2: {{col}}</template>
  <template let-col>3: {{col}}</template>
</my-table>
  `,
})
export class App {
  data = [
    ['apple', 'orange', 'banana'],
    ['cat', 'dog', 'bird'],
    ['car', 'bicycle', 'airplane'],
  ];
}

where row and column data is passed to an input and the layout for the cells passed as <template> elements (one for each column - some additional checks are probably useful like checking if the number of templates is >= the number of columns in data).

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
0

Actually it is quite easy to integrate DataTabes directly without using third party wrapper. Typings are already available in npm. It gives you opportunity to gradually extend your wrapper with required features.

kemsky
  • 14,727
  • 3
  • 32
  • 51