Skip to content

Commit

Permalink
feat(filter): add support for custom filters (#825)
Browse files Browse the repository at this point in the history
Fixes #632 , #569, #447
  • Loading branch information
craftycorvid authored and nnixaa committed Feb 19, 2019
1 parent f9da8de commit b4713d9
Show file tree
Hide file tree
Showing 11 changed files with 194 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Component } from '@angular/core';

import { CustomEditorComponent } from './custom-editor.component';
import { CustomRenderComponent } from './custom-render.component';
import { CustomFilterComponent } from './custom-filter.component';

@Component({
selector: 'advanced-example-custom-editor',
Expand Down Expand Up @@ -42,6 +43,10 @@ export class AdvancedExamplesCustomEditorComponent {
columns: {
id: {
title: 'ID',
filter: {
type: 'custom',
component: CustomFilterComponent
}
},
name: {
title: 'Full Name',
Expand Down
43 changes: 43 additions & 0 deletions src/app/pages/examples/custom-edit-view/custom-filter.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import {Component, OnChanges, OnInit, SimpleChanges} from '@angular/core';
import { FormControl } from '@angular/forms';
import { debounceTime, distinctUntilChanged, skip } from 'rxjs/operators';

import { DefaultFilter } from '../../../../ng2-smart-table';

@Component({
template: `
<input
#number
[ngClass]="inputClass"
[formControl]="inputControl"
class="form-control"
[placeholder]="column.title"
type="number">
`,
})
export class CustomFilterComponent extends DefaultFilter implements OnInit, OnChanges {
inputControl = new FormControl();

constructor() {
super();
}

ngOnInit() {
this.inputControl.valueChanges
.pipe(
distinctUntilChanged(),
debounceTime(this.delay),
)
.subscribe((value: number) => {
this.query = value !== null ? this.inputControl.value.toString() : '';
this.setFilter();
});
}

ngOnChanges(changes: SimpleChanges) {
if (changes.query) {
this.query = changes.query.currentValue;
this.inputControl.setValue(this.query);
}
}
}
3 changes: 3 additions & 0 deletions src/app/pages/examples/examples.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { BasicExampleMultiSelectComponent } from './various/basic-example-multi-
import { CustomEditorComponent } from './custom-edit-view/custom-editor.component';
import { BasicExampleSourceComponent } from './filter/basic-example-source.component';
import { CustomRenderComponent } from './custom-edit-view/custom-render.component';
import { CustomFilterComponent } from './custom-edit-view/custom-filter.component';
import { FilterExamplesComponent } from './filter/filter-examples.component';
import { ServerExamplesComponent } from './server/server-examples.component';
import { CustomViewEditExamplesComponent } from './custom-edit-view/custom-edit-view-examples.component';
Expand All @@ -40,6 +41,7 @@ const EXAMPLES_COMPONENTS = [
BasicExampleSourceComponent,
CustomEditorComponent,
CustomRenderComponent,
CustomFilterComponent,
FilterExamplesComponent,
ServerExamplesComponent,
CustomViewEditExamplesComponent,
Expand All @@ -62,6 +64,7 @@ const EXAMPLES_COMPONENTS = [
entryComponents: [
CustomEditorComponent,
CustomRenderComponent,
CustomFilterComponent,
ButtonViewComponent,
],
declarations: [
Expand Down
48 changes: 48 additions & 0 deletions src/ng2-smart-table/components/filter/custom-filter.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {
Component,
ComponentFactoryResolver, Input,
OnChanges,
OnDestroy,
SimpleChanges,
ViewChild,
ViewContainerRef
} from '@angular/core';

import { FilterDefault } from './filter-default';

@Component({
selector: 'custom-table-filter',
template: `<ng-template #dynamicTarget></ng-template>`,
})
export class CustomFilterComponent extends FilterDefault implements OnChanges, OnDestroy {
@Input() query: string;
customComponent: any;
@ViewChild('dynamicTarget', { read: ViewContainerRef }) dynamicTarget: any;

constructor(private resolver: ComponentFactoryResolver) {
super();
}

ngOnChanges(changes: SimpleChanges) {
if (this.column && !this.customComponent) {
const componentFactory = this.resolver.resolveComponentFactory(this.column.filter.component);
this.customComponent = this.dynamicTarget.createComponent(componentFactory);

// set @Inputs and @Outputs of custom component
this.customComponent.instance.query = this.query;
this.customComponent.instance.column = this.column;
this.customComponent.instance.source = this.source;
this.customComponent.instance.inputClass = this.inputClass;
this.customComponent.instance.filter.subscribe((event: any) => this.onFilter(event));
}
if (this.customComponent) {
this.customComponent.instance.ngOnChanges(changes);
}
}

ngOnDestroy() {
if (this.customComponent) {
this.customComponent.destroy();
}
}
}
38 changes: 38 additions & 0 deletions src/ng2-smart-table/components/filter/default-filter.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {Component, Input} from '@angular/core';

import {FilterDefault} from "./filter-default";

@Component({
selector: 'default-table-filter',
template: `
<ng-container [ngSwitch]="column.getFilterType()">
<select-filter *ngSwitchCase="'list'"
[query]="query"
[ngClass]="inputClass"
[column]="column"
(filter)="onFilter($event)">
</select-filter>
<checkbox-filter *ngSwitchCase="'checkbox'"
[query]="query"
[ngClass]="inputClass"
[column]="column"
(filter)="onFilter($event)">
</checkbox-filter>
<completer-filter *ngSwitchCase="'completer'"
[query]="query"
[ngClass]="inputClass"
[column]="column"
(filter)="onFilter($event)">
</completer-filter>
<input-filter *ngSwitchDefault
[query]="query"
[ngClass]="inputClass"
[column]="column"
(filter)="onFilter($event)">
</input-filter>
</ng-container>
`,
})
export class DefaultFilterComponent extends FilterDefault {
@Input() query: string;
}
23 changes: 23 additions & 0 deletions src/ng2-smart-table/components/filter/filter-default.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Output, EventEmitter, Input } from '@angular/core';

import { Column } from '../../lib/data-set/column';
import { DataSource } from '../../lib/data-source/data-source';

export class FilterDefault {

@Input() column: Column;
@Input() source: DataSource;
@Input() inputClass: string = '';

@Output() filter = new EventEmitter<any>();

query: string = '';

onFilter(query: string) {
this.source.addFilter({
field: this.column.id,
search: query,
filter: this.column.getFilterFunction(),
});
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core';
import { Component, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { FormControl } from '@angular/forms';
import { debounceTime, distinctUntilChanged, skip } from 'rxjs/operators';

Expand All @@ -15,7 +15,7 @@ import { DefaultFilter } from './default-filter';
placeholder="{{ column.title }}"/>
`,
})
export class InputFilterComponent extends DefaultFilter implements OnInit {
export class InputFilterComponent extends DefaultFilter implements OnInit, OnChanges {

inputControl = new FormControl();

Expand All @@ -38,4 +38,10 @@ export class InputFilterComponent extends DefaultFilter implements OnInit {
this.setFilter();
});
}

ngOnChanges(changes: SimpleChanges) {
if (changes.query) {
this.inputControl.setValue(this.query);
}
}
}
68 changes: 20 additions & 48 deletions src/ng2-smart-table/components/filter/filter.component.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,31 @@
import { Component, Input, Output, EventEmitter, OnChanges, SimpleChanges } from '@angular/core';

import { DataSource } from '../../lib/data-source/data-source';
import { Column } from '../../lib/data-set/column';
import { Component, OnChanges, SimpleChanges } from '@angular/core';
import { FilterDefault } from './filter-default';
import { Subscription } from 'rxjs';

@Component({
selector: 'ng2-smart-table-filter',
styleUrls: ['./filter.component.scss'],
template: `
<div class="ng2-smart-filter" *ngIf="column.isFilterable" [ngSwitch]="column.getFilterType()">
<select-filter *ngSwitchCase="'list'"
[query]="query"
[ngClass]="inputClass"
[column]="column"
(filter)="onFilter($event)">
</select-filter>
<checkbox-filter *ngSwitchCase="'checkbox'"
[query]="query"
[ngClass]="inputClass"
[column]="column"
(filter)="onFilter($event)">
</checkbox-filter>
<completer-filter *ngSwitchCase="'completer'"
[query]="query"
[ngClass]="inputClass"
[column]="column"
(filter)="onFilter($event)">
</completer-filter>
<input-filter *ngSwitchDefault
[query]="query"
[ngClass]="inputClass"
[column]="column"
(filter)="onFilter($event)">
</input-filter>
</div>
`,
<div class="ng2-smart-filter" *ngIf="column.isFilterable" [ngSwitch]="column.getFilterType()">
<custom-table-filter *ngSwitchCase="'custom'"
[query]="query"
[column]="column"
[source]="source"
[inputClass]="inputClass"
(filter)="onFilter($event)">
</custom-table-filter>
<default-table-filter *ngSwitchDefault
[query]="query"
[column]="column"
[source]="source"
[inputClass]="inputClass"
(filter)="onFilter($event)">
</default-table-filter>
</div>
`,
})
export class FilterComponent implements OnChanges {

@Input() column: Column;
@Input() source: DataSource;
@Input() inputClass: string = '';

@Output() filter = new EventEmitter<any>();

export class FilterComponent extends FilterDefault implements OnChanges {
query: string = '';

protected dataChangedSub: Subscription;

ngOnChanges(changes: SimpleChanges) {
Expand All @@ -70,12 +50,4 @@ export class FilterComponent implements OnChanges {
});
}
}

onFilter(query: string) {
this.source.addFilter({
field: this.column.id,
search: query,
filter: this.column.getFilterFunction(),
});
}
}
4 changes: 4 additions & 0 deletions src/ng2-smart-table/components/filter/filter.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { Ng2CompleterModule } from 'ng2-completer';

import { FilterComponent } from './filter.component';
import { DefaultFilterComponent } from "./default-filter.component";
import { CustomFilterComponent } from "./custom-filter.component";
import { CheckboxFilterComponent } from './filter-types/checkbox-filter.component';
import { CompleterFilterComponent } from './filter-types/completer-filter.component';
import { InputFilterComponent } from './filter-types/input-filter.component';
import { SelectFilterComponent } from './filter-types/select-filter.component';

const FILTER_COMPONENTS = [
FilterComponent,
DefaultFilterComponent,
CustomFilterComponent,
CheckboxFilterComponent,
CompleterFilterComponent,
InputFilterComponent,
Expand Down
1 change: 1 addition & 0 deletions src/ng2-smart-table/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export * from './ng2-smart-table.module';
export { ViewCell } from './components/cell/cell-view-mode/view-cell';
export { DefaultEditor, Editor } from './components/cell/cell-editors/default-editor';
export { DefaultFilter, Filter } from './components/filter/filter-types/default-filter'
export { Cell } from './lib/data-set/cell';
export { LocalDataSource } from './lib/data-source/local/local.data-source';
export { ServerDataSource } from './lib/data-source/server/server.data-source';
2 changes: 1 addition & 1 deletion src/ng2-smart-table/lib/data-set/column.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class Column {
sortDirection: string = '';
defaultSortDirection: string = '';
editor: { type: string, config: any, component: any } = { type: '', config: {}, component: null };
filter: { type: string, config: any } = { type: '', config: {} };
filter: { type: string, config: any, component: any } = { type: '', config: {}, component: null };
renderComponent: any = null;
compareFunction: Function;
valuePrepareFunction: Function;
Expand Down

0 comments on commit b4713d9

Please sign in to comment.