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

3
  • Is the filter supposed to be a search field that filters automatically or with a 'search' button? Commented Jan 20, 2017 at 18:06
  • yes, automatically after keyup Commented Jan 23, 2017 at 9:03
  • why to waste time and effort when you have an ng2-table here valor-software.com/ng2-table Follow the documentation for setting up Commented Feb 4, 2017 at 17:54

2 Answers 2

5
+50

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).

Sign up to request clarification or add additional context in comments.

3 Comments

It has to be used new component because it is my stylized table with sorting and search functionality
You can use custom components without any change in my approach. If you want to use the <table> element, you need to use attribute selectors for your custom components like <tr my-table-row>
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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.