From d4dc43c661182022af5685a73c9da8fdf860f142 Mon Sep 17 00:00:00 2001 From: Surya Teja K Date: Sun, 10 Jan 2021 13:53:01 +0530 Subject: [PATCH 1/4] feat: Add support for using Angular pipes to transform data --- .../app/advanced/using-ng-pipe.component.html | 32 ++++++++ .../app/advanced/using-ng-pipe.component.ts | 40 ++++++++++ .../advanced/using-pipe-snippet.component.ts | 78 +++++++++++++++++++ demo/src/app/app.component.html | 3 + demo/src/app/app.module.ts | 8 +- demo/src/app/app.routing.ts | 5 ++ src/angular-datatables.directive.ts | 32 +++++++- src/models/settings.ts | 9 +++ 8 files changed, 204 insertions(+), 3 deletions(-) create mode 100644 demo/src/app/advanced/using-ng-pipe.component.html create mode 100644 demo/src/app/advanced/using-ng-pipe.component.ts create mode 100644 demo/src/app/advanced/using-pipe-snippet.component.ts create mode 100644 src/models/settings.ts diff --git a/demo/src/app/advanced/using-ng-pipe.component.html b/demo/src/app/advanced/using-ng-pipe.component.html new file mode 100644 index 000000000..eba9f7eb1 --- /dev/null +++ b/demo/src/app/advanced/using-ng-pipe.component.html @@ -0,0 +1,32 @@ + +
+
+
+
+

+ You can use Angular Pipe to transform data on the table. +

+
+ +
+
+

Preview

+
+
+
+ +
+
+
diff --git a/demo/src/app/advanced/using-ng-pipe.component.ts b/demo/src/app/advanced/using-ng-pipe.component.ts new file mode 100644 index 000000000..5e615d49f --- /dev/null +++ b/demo/src/app/advanced/using-ng-pipe.component.ts @@ -0,0 +1,40 @@ +import { UpperCasePipe } from '@angular/common'; +import { Component, OnInit } from '@angular/core'; +import { ADTSettings } from 'angular-datatables/src/models/settings'; + +@Component({ + selector: 'app-using-ng-pipe', + templateUrl: './using-ng-pipe.component.html' +}) +export class UsingNgPipeComponent implements OnInit { + + constructor( + private pipeInstance: UpperCasePipe + ) { } + + dtOptions: ADTSettings = {} + + ngOnInit(): void { + + this.dtOptions = { + ajax: 'data/data.json', + columns: [ + { + title: 'ID', + data: 'id' + }, + { + title: 'First name', + data: 'firstName', + ngPipeInstance: this.pipeInstance + }, + { + title: 'Last name', + data: 'lastName', + ngPipeInstance: this.pipeInstance + } + ] + } + } + +} diff --git a/demo/src/app/advanced/using-pipe-snippet.component.ts b/demo/src/app/advanced/using-pipe-snippet.component.ts new file mode 100644 index 000000000..8d2f77398 --- /dev/null +++ b/demo/src/app/advanced/using-pipe-snippet.component.ts @@ -0,0 +1,78 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-using-pipe-snippet', + template: ` +
+

HTML

+
+
+
+

Typescript

+
+
+ ` +}) +export class UsingPipeSnippetComponent implements OnInit { + + constructor() { } + + htmlSnippet = ` +
+
+<table datatable [dtOptions]="dtOptions" class="row-border hover"></table>
+
+ `; + + tsSnippet = ` +
+
+import { UpperCasePipe } from '@angular/common';
+import { Component, OnInit } from '@angular/core';
+import { ADTSettings } from 'angular-datatables/src/models/settings';
+
+@Component({
+  selector: 'app-using-ng-pipe',
+  templateUrl: './using-ng-pipe.component.html'
+})
+export class UsingNgPipeComponent implements OnInit {
+
+  constructor(
+    private pipeInstance: UpperCasePipe // inject your Angular Pipe
+  ) { }
+
+  // Use ADTSettings instead of DataTables.Settings
+  dtOptions: ADTSettings = {};
+
+  ngOnInit(): void {
+
+    this.dtOptions = {
+      ajax: 'data/data.json',
+      columns: [
+        {
+          title: 'ID',
+          data: 'id'
+        },
+        {
+          title: 'First name',
+          data: 'firstName',
+          ngPipeInstance: this.pipeInstance  // <-- Pipe is used here
+        },
+        {
+          title: 'Last name',
+          data: 'lastName',
+          ngPipeInstance: this.pipeInstance  // <-- Pipe is used here
+        }
+      ]
+    };
+  }
+
+}
+
+
+ `; + + ngOnInit(): void { + } + +} diff --git a/demo/src/app/app.component.html b/demo/src/app/app.component.html index 472fc2229..f700149ad 100644 --- a/demo/src/app/app.component.html +++ b/demo/src/app/app.component.html @@ -89,6 +89,9 @@

  • Router link
  • +
  • + Using Angular Pipes +
  • diff --git a/demo/src/app/app.module.ts b/demo/src/app/app.module.ts index 68ae94f54..ab8a02b6d 100644 --- a/demo/src/app/app.module.ts +++ b/demo/src/app/app.module.ts @@ -57,12 +57,15 @@ import { ResponsiveExtensionConfigurationComponent } from './extensions/responsi import { SelectExtensionComponent } from './extensions/select-extension.component'; import { SelectExtensionSnippetComponent } from './extensions/select-extension-snippet.component'; import { SelectExtensionConfigurationComponent } from './extensions/select-extension-configuration.component'; +import { UsingNgPipeComponent } from './advanced/using-ng-pipe.component'; +import { UsingPipeSnippetComponent } from './advanced/using-pipe-snippet.component'; // HightlightJS import hljs from 'highlight.js/lib/highlight'; import javascript from 'highlight.js/lib/languages/javascript'; import typescript from 'highlight.js/lib/languages/typescript'; import xml from 'highlight.js/lib/languages/xml'; +import { UpperCasePipe } from '@angular/common'; hljs.registerLanguage('typescript', typescript); hljs.registerLanguage('javascript', javascript); @@ -114,7 +117,9 @@ hljs.registerLanguage('xml', xml); ResponsiveExtensionConfigurationComponent, SelectExtensionComponent, SelectExtensionSnippetComponent, - SelectExtensionConfigurationComponent + SelectExtensionConfigurationComponent, + UsingNgPipeComponent, + UsingPipeSnippetComponent ], imports: [ BrowserModule, @@ -125,6 +130,7 @@ hljs.registerLanguage('xml', xml); AppRoutingModule ], providers: [ + UpperCasePipe ], bootstrap: [AppComponent] }) diff --git a/demo/src/app/app.routing.ts b/demo/src/app/app.routing.ts index 63f884aa0..343670176 100644 --- a/demo/src/app/app.routing.ts +++ b/demo/src/app/app.routing.ts @@ -24,6 +24,7 @@ import { ButtonsExtensionComponent } from './extensions/buttons-extension.compon import { ColreorderExtensionComponent } from './extensions/colreorder-extension.component'; import { ResponsiveExtensionComponent } from './extensions/responsive-extension.component'; import { SelectExtensionComponent } from './extensions/select-extension.component'; +import { UsingNgPipeComponent } from './advanced/using-ng-pipe.component'; const routes: Routes = [ { @@ -95,6 +96,10 @@ const routes: Routes = [ path: 'advanced/router-link', component: RouterLinkComponent }, + { + path: 'advanced/using-pipe', + component: UsingNgPipeComponent + }, { path: 'extensions/buttons', component: ButtonsExtensionComponent diff --git a/src/angular-datatables.directive.ts b/src/angular-datatables.directive.ts index b75adfc94..7b45ee990 100644 --- a/src/angular-datatables.directive.ts +++ b/src/angular-datatables.directive.ts @@ -7,6 +7,7 @@ import { Directive, ElementRef, Input, OnDestroy, OnInit } from '@angular/core'; import { Subject } from 'rxjs'; +import { ADTSettings } from './models/settings'; @Directive({ selector: '[datatable]' @@ -16,7 +17,7 @@ export class DataTableDirective implements OnDestroy, OnInit { * The DataTable option you pass to configure your table. */ @Input() - dtOptions: DataTables.Settings = {}; + dtOptions: ADTSettings = {}; /** * This trigger is used if one wants to trigger manually the DT rendering @@ -62,7 +63,34 @@ export class DataTableDirective implements OnDestroy, OnInit { Promise.resolve(this.dtOptions).then(dtOptions => { // Using setTimeout as a "hack" to be "part" of NgZone setTimeout(() => { - this.dt = $(this.el.nativeElement).DataTable(dtOptions); + this.dt = $(this.el.nativeElement).DataTable({ + ...dtOptions, + rowCallback: (row, data, index) => { + if (dtOptions.columns) { + const columns = dtOptions.columns; + // Filter columns with pipe declared + const colsWithPipe = columns.filter(x => x.ngPipeInstance); + // Iterate + colsWithPipe.forEach(el => { + const pipe = el.ngPipeInstance; + // find index of column using `data` attr + const i = columns.findIndex(e => e.data == el.data); + // get element which holds data using index + const rowFromCol = row.childNodes.item(i); + // Transform data with Pipe + const rowVal = $(rowFromCol).text(); + const rowValAfter = pipe.transform(rowVal); + // Apply transformed string to + $(rowFromCol).text(rowValAfter); + }); + } + + // run user specified row callback if provided. + if (this.dtOptions.rowCallback) { + this.dtOptions.rowCallback(row, data, index); + } + } + }); resolve(this.dt); }); }); diff --git a/src/models/settings.ts b/src/models/settings.ts new file mode 100644 index 000000000..68561c1f1 --- /dev/null +++ b/src/models/settings.ts @@ -0,0 +1,9 @@ +import { PipeTransform } from '@angular/core'; + +export interface ADTSettings extends DataTables.Settings { + columns?: ADTColumns[]; +} +export interface ADTColumns extends DataTables.ColumnSettings { + /** Set instance of Angular pipe to transform the data of particular column */ + ngPipeInstance?: PipeTransform; +} From 1718e7e42628b411c29b045eca4cefcd3a4242c9 Mon Sep 17 00:00:00 2001 From: Surya Teja K Date: Mon, 11 Jan 2021 09:37:10 +0530 Subject: [PATCH 2/4] fix: changes as per review --- ...nippet.component.ts => using-ng-pipe-snippet.component.ts} | 0 demo/src/app/advanced/using-ng-pipe.component.ts | 4 ++-- demo/src/app/app.module.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename demo/src/app/advanced/{using-pipe-snippet.component.ts => using-ng-pipe-snippet.component.ts} (100%) diff --git a/demo/src/app/advanced/using-pipe-snippet.component.ts b/demo/src/app/advanced/using-ng-pipe-snippet.component.ts similarity index 100% rename from demo/src/app/advanced/using-pipe-snippet.component.ts rename to demo/src/app/advanced/using-ng-pipe-snippet.component.ts diff --git a/demo/src/app/advanced/using-ng-pipe.component.ts b/demo/src/app/advanced/using-ng-pipe.component.ts index 5e615d49f..0f77dac5d 100644 --- a/demo/src/app/advanced/using-ng-pipe.component.ts +++ b/demo/src/app/advanced/using-ng-pipe.component.ts @@ -12,7 +12,7 @@ export class UsingNgPipeComponent implements OnInit { private pipeInstance: UpperCasePipe ) { } - dtOptions: ADTSettings = {} + dtOptions: ADTSettings = {}; ngOnInit(): void { @@ -34,7 +34,7 @@ export class UsingNgPipeComponent implements OnInit { ngPipeInstance: this.pipeInstance } ] - } + }; } } diff --git a/demo/src/app/app.module.ts b/demo/src/app/app.module.ts index ab8a02b6d..7671cb8e2 100644 --- a/demo/src/app/app.module.ts +++ b/demo/src/app/app.module.ts @@ -58,7 +58,7 @@ import { SelectExtensionComponent } from './extensions/select-extension.componen import { SelectExtensionSnippetComponent } from './extensions/select-extension-snippet.component'; import { SelectExtensionConfigurationComponent } from './extensions/select-extension-configuration.component'; import { UsingNgPipeComponent } from './advanced/using-ng-pipe.component'; -import { UsingPipeSnippetComponent } from './advanced/using-pipe-snippet.component'; +import { UsingPipeSnippetComponent } from './advanced/using-ng-pipe-snippet.component'; // HightlightJS import hljs from 'highlight.js/lib/highlight'; From a174da244a652298454e6308e4a15fa3a830ceb4 Mon Sep 17 00:00:00 2001 From: Surya Teja K Date: Mon, 11 Jan 2021 09:52:35 +0530 Subject: [PATCH 3/4] fix: workaround for spread operator as it triggers rollup's 'this is undefined' error --- src/angular-datatables.directive.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/angular-datatables.directive.ts b/src/angular-datatables.directive.ts index 7b45ee990..8eb4c34bf 100644 --- a/src/angular-datatables.directive.ts +++ b/src/angular-datatables.directive.ts @@ -63,8 +63,8 @@ export class DataTableDirective implements OnDestroy, OnInit { Promise.resolve(this.dtOptions).then(dtOptions => { // Using setTimeout as a "hack" to be "part" of NgZone setTimeout(() => { - this.dt = $(this.el.nativeElement).DataTable({ - ...dtOptions, + // Assign DT properties here + let options: ADTSettings = { rowCallback: (row, data, index) => { if (dtOptions.columns) { const columns = dtOptions.columns; @@ -90,7 +90,10 @@ export class DataTableDirective implements OnDestroy, OnInit { this.dtOptions.rowCallback(row, data, index); } } - }); + }; + // merge user's config with ours + options = Object.assign({}, dtOptions, options); + this.dt = $(this.el.nativeElement).DataTable(options); resolve(this.dt); }); }); From 0d28c6a36816e101655e3624b3b6eb8c76b14140 Mon Sep 17 00:00:00 2001 From: Surya Teja K Date: Tue, 12 Jan 2021 09:35:30 +0530 Subject: [PATCH 4/4] fix: rename snippet class name and selector --- demo/src/app/advanced/using-ng-pipe-snippet.component.ts | 4 ++-- demo/src/app/advanced/using-ng-pipe.component.html | 2 +- demo/src/app/app.module.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/demo/src/app/advanced/using-ng-pipe-snippet.component.ts b/demo/src/app/advanced/using-ng-pipe-snippet.component.ts index 8d2f77398..563c56501 100644 --- a/demo/src/app/advanced/using-ng-pipe-snippet.component.ts +++ b/demo/src/app/advanced/using-ng-pipe-snippet.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; @Component({ - selector: 'app-using-pipe-snippet', + selector: 'app-using-ng-pipe-snippet', template: `

    HTML

    @@ -13,7 +13,7 @@ import { Component, OnInit } from '@angular/core';
    ` }) -export class UsingPipeSnippetComponent implements OnInit { +export class UsingNgPipeSnippetComponent implements OnInit { constructor() { } diff --git a/demo/src/app/advanced/using-ng-pipe.component.html b/demo/src/app/advanced/using-ng-pipe.component.html index eba9f7eb1..70e70ddc4 100644 --- a/demo/src/app/advanced/using-ng-pipe.component.html +++ b/demo/src/app/advanced/using-ng-pipe.component.html @@ -26,7 +26,7 @@

    Preview

    - + diff --git a/demo/src/app/app.module.ts b/demo/src/app/app.module.ts index 7671cb8e2..ad9bcec7a 100644 --- a/demo/src/app/app.module.ts +++ b/demo/src/app/app.module.ts @@ -58,7 +58,7 @@ import { SelectExtensionComponent } from './extensions/select-extension.componen import { SelectExtensionSnippetComponent } from './extensions/select-extension-snippet.component'; import { SelectExtensionConfigurationComponent } from './extensions/select-extension-configuration.component'; import { UsingNgPipeComponent } from './advanced/using-ng-pipe.component'; -import { UsingPipeSnippetComponent } from './advanced/using-ng-pipe-snippet.component'; +import { UsingNgPipeSnippetComponent } from './advanced/using-ng-pipe-snippet.component'; // HightlightJS import hljs from 'highlight.js/lib/highlight'; @@ -119,7 +119,7 @@ hljs.registerLanguage('xml', xml); SelectExtensionSnippetComponent, SelectExtensionConfigurationComponent, UsingNgPipeComponent, - UsingPipeSnippetComponent + UsingNgPipeSnippetComponent ], imports: [ BrowserModule,