{
13 | const component = this.registeredFilters[type];
14 |
15 | return component;
16 | }
17 | }
--------------------------------------------------------------------------------
/projects/material-dynamic-table/src/lib/table-cell/cell-types/date-cell.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Input, OnInit } from '@angular/core';
2 | import { CellComponent } from './cell.component';
3 | import { ColumnConfig } from '../../column-config.model';
4 |
5 | @Component({
6 | selector: 'mdt-date-cell',
7 | template: '{{ row[column.name] | date:dateFormat }}'
8 | })
9 | export class DateCellComponent implements CellComponent, OnInit {
10 | @Input() column: ColumnConfig;
11 | @Input() row: object;
12 |
13 | dateFormat = 'short';
14 |
15 | ngOnInit() {
16 | if (this.column.options) {
17 | if (this.column.options.dateFormat) {
18 | this.dateFormat = this.column.options.dateFormat;
19 | }
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/projects/material-dynamic-table/src/lib/table-cell/cell-types/text-cell.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Input } from '@angular/core';
2 | import { CellComponent } from './cell.component';
3 | import { ColumnConfig } from '../../column-config.model';
4 |
5 | @Component({
6 | selector: 'mdt-text-cell',
7 | template: '{{ row[column.name] }}'
8 | })
9 | export class TextCellComponent implements CellComponent {
10 | @Input() column: ColumnConfig;
11 | @Input() row: object;
12 | }
--------------------------------------------------------------------------------
/projects/material-dynamic-table/src/lib/table-cell/cell.directive.ts:
--------------------------------------------------------------------------------
1 | import { Directive, ViewContainerRef } from '@angular/core';
2 |
3 | @Directive({
4 | selector: '[mdtCellHost]',
5 | })
6 | export class CellDirective {
7 | constructor(public viewContainerRef: ViewContainerRef) {}
8 | }
--------------------------------------------------------------------------------
/projects/material-dynamic-table/src/lib/table-cell/table-cell.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, ComponentFactoryResolver, Input, ViewChild, OnInit, ChangeDetectionStrategy } from '@angular/core';
2 | import { CellDirective } from './cell.directive';
3 | import { CellService } from './cell-types/cell.service';
4 | import { CellComponent } from './cell-types/cell.component';
5 | import { ColumnConfig } from '../column-config.model';
6 |
7 | @Component({
8 | selector: 'mdt-table-cell',
9 | template: '',
10 | changeDetection: ChangeDetectionStrategy.OnPush
11 | })
12 | export class TableCellComponent implements OnInit {
13 | @ViewChild(CellDirective, { static: true }) cellHost: CellDirective;
14 |
15 | @Input() row: object;
16 | @Input() column: ColumnConfig;
17 |
18 | constructor(
19 | private readonly cellService: CellService,
20 | private readonly componentFactoryResolver: ComponentFactoryResolver) { }
21 |
22 | ngOnInit() {
23 | this.initCell();
24 | }
25 |
26 | initCell() {
27 | const cellComponent = this.cellService.getCell(this.column.type);
28 | const componentFactory = this.componentFactoryResolver.resolveComponentFactory(cellComponent);
29 | const viewContainerRef = this.cellHost.viewContainerRef;
30 | viewContainerRef.clear();
31 | const componentRef = viewContainerRef.createComponent(componentFactory);
32 | const cell = componentRef.instance as CellComponent;
33 | cell.row = this.row;
34 | cell.column = this.column;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/projects/material-dynamic-table/src/public_api.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Public API Surface of dynamic-table
3 | */
4 |
5 | export * from './lib/dynamic-table.component';
6 | export * from './lib/multi-sort/multi-sort.directive';
7 | export * from './lib/multi-sort/multi-sort-data-source';
8 | export * from './lib/multi-sort/table-filter';
9 | export * from './lib/column-resize/resizable-directives/resizable';
10 | export * from './lib/column-resize/column-resize-directives/column-resize';
11 | export * from './lib/column-resize/column-resize-module';
12 | export * from './lib/column-resize/overlay-handle';
13 | export * from './lib/dynamic-table.module';
14 |
--------------------------------------------------------------------------------
/projects/material-dynamic-table/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js';
4 | import 'zone.js/testing';
5 | import { getTestBed } from '@angular/core/testing';
6 | import {
7 | BrowserDynamicTestingModule,
8 | platformBrowserDynamicTesting
9 | } from '@angular/platform-browser-dynamic/testing';
10 |
11 | // First, initialize the Angular testing environment.
12 | getTestBed().initTestEnvironment(
13 | BrowserDynamicTestingModule,
14 | platformBrowserDynamicTesting()
15 | );
16 |
--------------------------------------------------------------------------------
/projects/material-dynamic-table/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../out-tsc/lib",
5 | "declarationMap": true,
6 | "module": "es2022",
7 | "moduleResolution": "node",
8 | "declaration": true,
9 | "sourceMap": true,
10 | "inlineSources": true,
11 | "emitDecoratorMetadata": true,
12 | "experimentalDecorators": true,
13 | "importHelpers": true,
14 | "types": [],
15 | "lib": [
16 | "dom",
17 | "es2022"
18 | ]
19 | },
20 | "angularCompilerOptions": {
21 | "annotateForClosureCompiler": true,
22 | "skipTemplateCodegen": true,
23 | "strictMetadataEmit": true,
24 | "fullTemplateTypeCheck": true,
25 | "strictInjectionParameters": true,
26 | "enableResourceInlining": true
27 | },
28 | "exclude": [
29 | "src/test.ts",
30 | "**/*.spec.ts"
31 | ]
32 | }
33 |
--------------------------------------------------------------------------------
/projects/material-dynamic-table/tsconfig.lib.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.lib.json",
3 | "compilerOptions": {
4 | "declarationMap": false
5 | },
6 | "angularCompilerOptions": {
7 | "enableIvy": true,
8 | "compilationMode": "partial"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/projects/material-dynamic-table/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../out-tsc/spec",
5 | "types": [
6 | "jasmine",
7 | "node"
8 | ]
9 | },
10 | "files": [
11 | "src/test.ts"
12 | ],
13 | "include": [
14 | "**/*.spec.ts",
15 | "**/*.d.ts"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/projects/material-dynamic-table/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tslint.json",
3 | "rules": {
4 | "directive-selector": [
5 | true,
6 | "attribute",
7 | "mdt",
8 | "camelCase"
9 | ],
10 | "component-selector": [
11 | true,
12 | "element",
13 | "mdt",
14 | "kebab-case"
15 | ]
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/.browserslistrc:
--------------------------------------------------------------------------------
1 | # This file is currently used by autoprefixer to adjust CSS to support the below specified browsers
2 | # For additional information regarding the format and rule options, please see:
3 | # https://github.com/browserslist/browserslist#queries
4 | #
5 | # For IE 9-11 support, please remove 'not' from the last line of the file and adjust as needed
6 |
7 | > 0.5%
8 | last 2 versions
9 | Firefox ESR
10 | not dead
11 | not IE 9-11
--------------------------------------------------------------------------------
/src/app/app.component.css:
--------------------------------------------------------------------------------
1 | .table-container {
2 | height: 300px;
3 | overflow: auto;
4 | }
5 |
6 | .buttons {
7 | margin-top: 10px;
8 | }
9 |
--------------------------------------------------------------------------------
/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Welcome to {{ title }}!
5 |
6 |

7 |
8 |
9 |
11 |
12 |
13 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/app/app.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed, waitForAsync } from '@angular/core/testing';
2 | import { AppComponent } from './app.component';
3 | import { DynamicTableModule } from 'material-dynamic-table';
4 | import { MatPaginatorModule } from '@angular/material/paginator';
5 | import { NoopAnimationsModule } from '@angular/platform-browser/animations';
6 |
7 | describe('AppComponent', () => {
8 | beforeEach(waitForAsync(() => {
9 | TestBed.configureTestingModule({
10 | declarations: [
11 | AppComponent
12 | ],
13 | imports: [
14 | DynamicTableModule,
15 | MatPaginatorModule,
16 | NoopAnimationsModule
17 | ],
18 | }).compileComponents();
19 | }));
20 |
21 | it('should create the app', waitForAsync(() => {
22 | const fixture = TestBed.createComponent(AppComponent);
23 | const app = fixture.debugElement.componentInstance;
24 | expect(app).toBeTruthy();
25 | }));
26 |
27 | it(`should have as title 'material-dynamic-table-demo'`, waitForAsync(() => {
28 | const fixture = TestBed.createComponent(AppComponent);
29 | const app = fixture.debugElement.componentInstance;
30 | expect(app.title).toEqual('material-dynamic-table-demo');
31 | }));
32 |
33 | it('should render title in a h1 tag', waitForAsync(() => {
34 | const fixture = TestBed.createComponent(AppComponent);
35 | fixture.detectChanges();
36 | const compiled = fixture.debugElement.nativeElement;
37 | expect(compiled.querySelector('h1').textContent).toContain('Welcome to material-dynamic-table-demo!');
38 | }));
39 | });
40 |
--------------------------------------------------------------------------------
/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, ViewChild } from '@angular/core';
2 | import { MatPaginator } from '@angular/material/paginator';
3 | import { FilteredDataSource } from './data-source/filtered-data-source';
4 | import { ColumnConfig, DynamicTableComponent } from 'material-dynamic-table';
5 | import { Product } from './product';
6 | import { TextFilter } from './filters/text-filter/text-filter.model';
7 | import { DateFilter } from './filters/date-filter/date-filter.model';
8 |
9 | @Component({
10 | selector: 'ld-root',
11 | templateUrl: './app.component.html',
12 | styleUrls: ['./app.component.css']
13 | })
14 | export class AppComponent {
15 | title = 'material-dynamic-table-demo';
16 |
17 | @ViewChild(DynamicTableComponent, { static: true }) dynamicTable: DynamicTableComponent;
18 |
19 | @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
20 |
21 | columns: ColumnConfig[] = [
22 | {
23 | name: 'product',
24 | displayName: 'Product',
25 | type: 'string',
26 | sticky: 'start',
27 | hint: 'Product name'
28 | },
29 | {
30 | name: 'description',
31 | displayName: 'Description',
32 | type: 'string',
33 | sort: false,
34 | hint: 'Product Description',
35 | resizable: { minWidth: 120 }
36 | },
37 | {
38 | name: 'category',
39 | displayName: 'Category',
40 | type: 'string',
41 | resizable: { maxWidth: 200 }
42 | },
43 | {
44 | name: 'recievedOn',
45 | displayName: 'Recieved On',
46 | type: 'date',
47 | hint: 'Date product was received on',
48 | resizable: { minWidth: 130, maxWidth: 200 }
49 | },
50 | {
51 | name: 'created',
52 | displayName: 'Created Date',
53 | type: 'date',
54 | options: {
55 | dateFormat: 'shortDate'
56 | },
57 | hint: 'Date entry was created',
58 | resizable: true
59 | },
60 | {
61 | name: '',
62 | type: 'options',
63 | sticky: 'end',
64 | sort: false
65 | }
66 | ];
67 |
68 | data: Product[] = [
69 | {
70 | product: 'Mouse',
71 | description: 'Fast and wireless',
72 | category: 'Peripherals',
73 | recievedOn: new Date('2018-01-02T11:05:53.212Z'),
74 | created: new Date('2015-04-22T18:12:21.111Z')
75 | },
76 | {
77 | product: 'Keyboard',
78 | description: 'Loud and Mechanical',
79 | category: 'Peripherals',
80 | recievedOn: new Date('2018-06-09T12:08:23.511Z'),
81 | created: new Date('2015-03-11T11:44:11.431Z')
82 | },
83 | {
84 | product: 'Laser',
85 | description: 'It\'s bright',
86 | category: 'Space',
87 | recievedOn: new Date('2017-05-22T18:25:43.511Z'),
88 | created: new Date('2015-04-21T17:15:23.111Z')
89 | },
90 | {
91 | product: 'Baby food',
92 | description: 'It\'s good for you',
93 | category: 'Food',
94 | recievedOn: new Date('2017-08-26T18:25:43.511Z'),
95 | created: new Date('2016-01-01T01:25:13.055Z')
96 | },
97 | {
98 | product: 'Coffee',
99 | description: 'Prepared from roasted coffee beans',
100 | category: 'Food',
101 | recievedOn: new Date('2015-04-16T23:52:23.565Z'),
102 | created: new Date('2016-12-21T21:05:03.253Z')
103 | },
104 | {
105 | product: 'Cheese',
106 | description: 'A dairy product',
107 | category: 'Food',
108 | recievedOn: new Date('2017-11-06T21:22:53.542Z'),
109 | created: new Date('2014-02-11T11:34:12.442Z')
110 | },
111 | {
112 | product: 'Floppy disk',
113 | description: 'It belongs in a museum',
114 | category: 'Storage',
115 | recievedOn: new Date('2015-10-12T11:12:42.621Z'),
116 | created: new Date('2013-03-12T21:54:31.221Z')
117 | },
118 | {
119 | product: 'Fan',
120 | description: 'It will blow you away',
121 | category: 'Hardware',
122 | recievedOn: new Date('2014-05-04T01:22:35.412Z'),
123 | created: new Date('2014-03-18T23:14:18.426Z')
124 | }
125 | ];
126 |
127 | dataSource = new FilteredDataSource(this.data);
128 |
129 | clearFilters() {
130 | this.dynamicTable.clearFilters();
131 | this.dynamicTable.setSort([]);
132 | }
133 |
134 | setFilter() {
135 | const createdColumnName = 'created';
136 |
137 | this.dynamicTable.setSort([{ id: 'category', direction: 'asc' }, { id: 'product', direction: 'desc' }]);
138 |
139 | const appliedFilter = this.dynamicTable.getFilter(createdColumnName);
140 | if (!appliedFilter) {
141 | const filter = new DateFilter(createdColumnName);
142 | filter.fromDate = new Date(2015, 1, 1);
143 | filter.toDate = new Date(2015, 12, 31);
144 |
145 | this.dynamicTable.setFilter(createdColumnName, filter);
146 | } else {
147 | const columnName = 'description';
148 | const filter = new TextFilter(columnName);
149 | filter.value = 'Loud';
150 |
151 | this.dynamicTable.setFilter(columnName, filter);
152 | }
153 | }
154 |
155 | onRowClick(row: any) {
156 | console.log(row);
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { BrowserModule } from '@angular/platform-browser';
3 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
4 | import { FormsModule } from '@angular/forms';
5 |
6 | import { MatButtonModule } from '@angular/material/button';
7 | import { MatInputModule } from '@angular/material/input';
8 | import { MatDialogModule } from '@angular/material/dialog';
9 | import { MatDatepickerModule } from '@angular/material/datepicker';
10 | import { MatNativeDateModule } from '@angular/material/core';
11 | import { MatMenuModule } from '@angular/material/menu';
12 | import { MatIconModule } from '@angular/material/icon';
13 | import { MatPaginatorModule } from '@angular/material/paginator';
14 |
15 | import { OptionsCellComponent } from './cells/options-cell/options-cell.component';
16 |
17 | import { TextFilterComponent } from './filters/text-filter/text-filter.component';
18 | import { DateFilterComponent } from './filters/date-filter/date-filter.component';
19 |
20 | import { CellService, ColumnFilterService, DynamicTableModule } from 'material-dynamic-table';
21 |
22 | import { AppComponent } from './app.component';
23 |
24 | @NgModule({
25 | declarations: [
26 | AppComponent,
27 | OptionsCellComponent,
28 | TextFilterComponent,
29 | DateFilterComponent
30 | ],
31 | imports: [
32 | BrowserModule,
33 | BrowserAnimationsModule,
34 | DynamicTableModule,
35 | FormsModule,
36 | MatButtonModule,
37 | MatInputModule,
38 | MatDialogModule,
39 | MatDatepickerModule,
40 | MatNativeDateModule,
41 | MatMenuModule,
42 | MatIconModule,
43 | MatPaginatorModule
44 | ],
45 | providers: [],
46 | bootstrap: [AppComponent]
47 | })
48 | export class AppModule {
49 | constructor(private readonly cellService: CellService, private readonly columnFilterService: ColumnFilterService) {
50 | cellService.registerCell('options', OptionsCellComponent);
51 |
52 | columnFilterService.registerFilter('string', TextFilterComponent);
53 | columnFilterService.registerFilter('date', DateFilterComponent);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/app/cells/options-cell/options-cell.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/app/cells/options-cell/options-cell.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Input } from '@angular/core';
2 | import { CellComponent, ColumnConfig } from 'material-dynamic-table';
3 | import { Product } from '../../product';
4 |
5 | @Component({
6 | selector: 'ld-options-cell',
7 | templateUrl: './options-cell.component.html'
8 | })
9 | export class OptionsCellComponent implements CellComponent {
10 | @Input()
11 | column: ColumnConfig;
12 |
13 | @Input()
14 | row: Product;
15 |
16 | constructor() {}
17 |
18 | showDetails() {
19 | const productName = this.row.product;
20 |
21 | alert(`Product name is ${productName}.`);
22 | }
23 | }
--------------------------------------------------------------------------------
/src/app/data-source/filtered-data-source.ts:
--------------------------------------------------------------------------------
1 | import { MdtTableDataSource, TableFilter } from 'material-dynamic-table';
2 |
3 | export class FilteredDataSource extends MdtTableDataSource {
4 |
5 | filterPredicate = (data: T): boolean => {
6 | if (!this.filters || !this.filters.length) {
7 | return true;
8 | }
9 |
10 | const result = this.filters.reduce((visible: boolean, tableFilter: TableFilter) => {
11 | if (!visible) {
12 | return visible;
13 | }
14 |
15 | const filter = tableFilter.getFilter();
16 |
17 | return Object.keys(filter).reduce((show, columnName) => {
18 | if (!show) {
19 | return show;
20 | }
21 | return this.matchesFilter(filter[columnName], data[columnName]);
22 | }, true);
23 | }, true);
24 |
25 | return result;
26 | }
27 |
28 | private matchesFilter(filterForColumn: any, dataForColumn: any): boolean {
29 |
30 | if (filterForColumn.contains && dataForColumn.indexOf(filterForColumn.contains) !== -1) {
31 | return true;
32 | }
33 |
34 | if (filterForColumn.le && filterForColumn.ge) {
35 | if (dataForColumn.getTime() >= filterForColumn.ge.getTime() && dataForColumn.getTime() <= filterForColumn.le.getTime()) {
36 | return true;
37 | }
38 | } else if (filterForColumn.ge && dataForColumn.getTime() >= filterForColumn.ge.getTime()) {
39 | return true;
40 | } else if (filterForColumn.le && dataForColumn.getTime() <= filterForColumn.le.getTime()) {
41 | return true;
42 | }
43 |
44 | return false;
45 | }
46 | }
--------------------------------------------------------------------------------
/src/app/filters/date-filter/date-filter.component.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/filters/date-filter/date-filter.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Inject, OnInit } from '@angular/core';
2 | import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
3 | import { DateFilter } from './date-filter.model';
4 | import { ColumnFilter } from 'material-dynamic-table';
5 |
6 | @Component({
7 | selector: 'ld-date-filter',
8 | templateUrl: './date-filter.component.html'
9 | })
10 | export class DateFilterComponent implements OnInit {
11 |
12 | model: DateFilter;
13 |
14 | displayName: string | undefined;
15 |
16 | public constructor(
17 | private readonly dialogRef: MatDialogRef,
18 | @Inject(MAT_DIALOG_DATA) private readonly filterData: ColumnFilter) { }
19 |
20 | ngOnInit() {
21 | this.displayName = this.filterData.column.displayName;
22 | this.model = this.filterData.filter || new DateFilter(this.filterData.column.name);
23 | }
24 |
25 | apply() {
26 | if (this.model.fromDate || this.model.toDate) {
27 | this.dialogRef.close(this.model);
28 | } else {
29 | this.dialogRef.close('');
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/src/app/filters/date-filter/date-filter.model.ts:
--------------------------------------------------------------------------------
1 | import { DatePipe } from '@angular/common';
2 | import { FilterDescription, TableFilter } from 'material-dynamic-table';
3 |
4 | export class DateFilter implements TableFilter, FilterDescription {
5 | fromDate: Date;
6 | toDate: Date;
7 |
8 | public constructor(private readonly column: string) {
9 | }
10 |
11 | getFilter(): object {
12 | const filter = {};
13 |
14 | if (this.fromDate && this.toDate) {
15 | filter[this.column] = { ge: this.fromDate, le: this.toDate };
16 | } else if (this.fromDate) {
17 | filter[this.column] = { ge: this.fromDate };
18 | } else if (this.toDate) {
19 | filter[this.column] = { le: this.toDate };
20 | }
21 |
22 | return filter;
23 | }
24 |
25 | getDescription() {
26 | if (!this.fromDate && !this.toDate) {
27 | return null;
28 | }
29 |
30 | const datePipe = new DatePipe('en-US');
31 | const formatDate = (date: Date) => datePipe.transform(date, 'shortDate');
32 |
33 | if (this.fromDate && this.toDate) {
34 | return `is between ${formatDate(this.fromDate)} and ${formatDate(this.toDate)}`;
35 | } else if (this.fromDate) {
36 | return `is after ${formatDate(this.fromDate)}`;
37 | } else if (this.toDate) {
38 | return `is before ${formatDate(this.toDate)}`;
39 | } else {
40 | return null;
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/src/app/filters/text-filter/text-filter.component.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/filters/text-filter/text-filter.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, Inject, OnInit } from '@angular/core';
2 | import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
3 | import { TextFilter } from './text-filter.model';
4 | import { ColumnFilter } from 'material-dynamic-table';
5 |
6 | @Component({
7 | selector: 'ld-text-filter',
8 | templateUrl: './text-filter.component.html'
9 | })
10 | export class TextFilterComponent implements OnInit {
11 |
12 | model: TextFilter;
13 |
14 | displayName: string | undefined;
15 |
16 | public constructor(
17 | private readonly dialogRef: MatDialogRef,
18 | @Inject(MAT_DIALOG_DATA) private readonly filterData: ColumnFilter) { }
19 |
20 | ngOnInit() {
21 | this.displayName = this.filterData.column.displayName;
22 | this.model = this.filterData.filter || new TextFilter(this.filterData.column.name);
23 | }
24 |
25 | apply() {
26 | if (this.model.value) {
27 | this.dialogRef.close(this.model);
28 | } else {
29 | this.dialogRef.close('');
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/src/app/filters/text-filter/text-filter.model.ts:
--------------------------------------------------------------------------------
1 | import { FilterDescription, TableFilter } from 'material-dynamic-table';
2 |
3 | export class TextFilter implements TableFilter, FilterDescription {
4 | value: string;
5 |
6 | public constructor(private readonly column: string) {
7 | this.value = '';
8 | }
9 |
10 | getFilter(): object {
11 | const filter = {};
12 |
13 | filter[this.column] = { contains: this.value };
14 |
15 | return filter;
16 | }
17 |
18 | getDescription() {
19 | if (!this.value) {
20 | return null;
21 | }
22 |
23 | return `contains '${this.value}'`;
24 | }
25 | }
--------------------------------------------------------------------------------
/src/app/product.ts:
--------------------------------------------------------------------------------
1 | export class Product {
2 | product: string;
3 | description: string;
4 | category: string;
5 | recievedOn: Date;
6 | created: Date;
7 | }
--------------------------------------------------------------------------------
/src/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/relair/material-dynamic-table/023276a697eab0d6d96f9eee702105f87ff71877/src/assets/.gitkeep
--------------------------------------------------------------------------------
/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // This file can be replaced during build by using the `fileReplacements` array.
2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
3 | // The list of file replacements can be found in `angular.json`.
4 |
5 | export const environment = {
6 | production: false
7 | };
8 |
9 | /*
10 | * For easier debugging in development mode, you can import the following file
11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
12 | *
13 | * This import should be commented out in production mode because it will have a negative impact
14 | * on performance if an error is thrown.
15 | */
16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI.
17 |
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/relair/material-dynamic-table/023276a697eab0d6d96f9eee702105f87ff71877/src/favicon.ico
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | LibDemo
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, '../coverage'),
20 | reports: ['html', 'lcovonly'],
21 | fixWebpackSourcePaths: true
22 | },
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false
30 | });
31 | };
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { enableProdMode } from '@angular/core';
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
3 |
4 | import { AppModule } from './app/app.module';
5 | import { environment } from './environments/environment';
6 |
7 | if (environment.production) {
8 | enableProdMode();
9 | }
10 |
11 | platformBrowserDynamic().bootstrapModule(AppModule)
12 | .catch(err => console.error(err));
13 |
14 |
--------------------------------------------------------------------------------
/src/styles.css:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
--------------------------------------------------------------------------------
/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js';
4 | import 'zone.js/testing';
5 | import { getTestBed } from '@angular/core/testing';
6 | import {
7 | BrowserDynamicTestingModule,
8 | platformBrowserDynamicTesting
9 | } from '@angular/platform-browser-dynamic/testing';
10 |
11 | // First, initialize the Angular testing environment.
12 | getTestBed().initTestEnvironment(
13 | BrowserDynamicTestingModule,
14 | platformBrowserDynamicTesting()
15 | );
16 |
--------------------------------------------------------------------------------
/src/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/app",
5 | "types": []
6 | },
7 | "exclude": [
8 | "test.ts",
9 | "**/*.spec.ts"
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/src/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/spec",
5 | "types": [
6 | "jasmine",
7 | "node"
8 | ]
9 | },
10 | "files": [
11 | "test.ts"
12 | ],
13 | "include": [
14 | "**/*.spec.ts",
15 | "**/*.d.ts"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/src/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tslint.json",
3 | "rules": {
4 | "directive-selector": [
5 | true,
6 | "attribute",
7 | "ld",
8 | "camelCase"
9 | ],
10 | "component-selector": [
11 | true,
12 | "element",
13 | "ld",
14 | "kebab-case"
15 | ]
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "baseUrl": "./",
5 | "outDir": "./dist/out-tsc",
6 | "sourceMap": true,
7 | "declaration": false,
8 | "module": "es2022",
9 | "moduleResolution": "node",
10 | "emitDecoratorMetadata": true,
11 | "experimentalDecorators": true,
12 | "strictNullChecks": true,
13 | "strictFunctionTypes": true,
14 | "noImplicitThis": true,
15 | "target": "ES2022",
16 | "typeRoots": [
17 | "node_modules/@types"
18 | ],
19 | "lib": [
20 | "es2022",
21 | "dom"
22 | ],
23 | "paths": {
24 | "material-dynamic-table": [
25 | "dist/material-dynamic-table"
26 | ],
27 | "material-dynamic-table/*": [
28 | "dist/material-dynamic-table/*"
29 | ]
30 | },
31 | "useDefineForClassFields": false
32 | }
33 | }
34 |
--------------------------------------------------------------------------------