ng2-smart-table
ng2-smart-table copied to clipboard
Date Range Filter for date column
Hi all,
I want to use a date range filter for a date column, How can i do that ?
I think the filter logic has to be provided by you . You can do this by writing an own filterFunction for that column (currently not working when the column-filter control is hidden - see #457).
As I have the subheader hidden in my application I cannot give you a hint for this (if your question goes in this direction).
@sahayarex could you put the date-range filter to the ng2-smart-table column ?
I am trying to set a date range filter, considering issue #457, i still don't know how can I change the template of the filter on the column to accept two values and accordingly filter function to accept three parameters? any idea?
no, unfortunately not. I just gave up :(
On Thu, Nov 16, 2017 at 3:05 PM, Kevin Barrientos [email protected] wrote:
@shilan https://github.com/shilan Did you found any solution?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/akveo/ng2-smart-table/issues/459#issuecomment-344932242, or mute the thread https://github.com/notifications/unsubscribe-auth/AH1ZbZEgnHEbIZqqAk9MAd3ZOWB_kbUFks5s3EE9gaJpZM4OmGN- .
Same issue here, would be great to have filtering from two or more values
Hi @sahayarex , you have to go with the implementation of custom-filters.
I implemented the same thing,


here is my custom filter:
import {Component, OnChanges, OnInit, SimpleChanges} from '@angular/core';
import { FormControl } from '@angular/forms';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
import { DefaultFilter } from 'ng2-smart-table';
@Component({
template: `
<input nbInput placeholder="{{column.title}}" [formControl]="inputControl" [nbDatepicker]="rangepicker">
<nb-rangepicker #rangepicker></nb-rangepicker>
`,
})
export class DateFilterComponent extends DefaultFilter implements OnInit, OnChanges {
inputControl = new FormControl();
constructor() {
super();
}
ngOnInit() {
this.inputControl.valueChanges
.pipe(
distinctUntilChanged(),
debounceTime(this.delay),
)
.subscribe((value: string) => {
if(this.inputControl.status === 'VALID')
{
this.query = value !== null ? JSON.stringify(this.inputControl.value) : "";
this.setFilter();
}
});
}
ngOnChanges(changes: SimpleChanges) {
if (changes.query) {
this.query = changes.query.currentValue;
this.inputControl.setValue(this.inputControl.value);
}
}
}
and here how I attached it with settings
if(this.attributes[one_opt].datatype == 'datetime64[ns]')
{
column_conf['renderComponent'] = DateRenderComponent;
column_conf["filter"] = {
type: 'custom',
component: DateFilterComponent
}
}
Hi @DanishAbsar This looks great but i did not successfully implement this, can you please send some working demo? Thanks!
Hi @DanishAbsar This looks great but i did not successfully implement this, can you please send some working demo? Thanks!
Hello @nebojsajsimic I think i almost put all required code, if you implement the procedure as I stated, then please let me know the error you are getting, or you can share your setting which you feeding in the smart table through .ts
@DanishAbsar The problem im having is that my date does not get filter, it shows the date in the filter but it doesnt filter between the dates
@DanishAbsar can you share the code for DateRenderComponent ?
@DanishAbsar thanks for the sample code, but I could still not get it working. Are you able to post a working example?
I have the example of @DanishAbsar working:
1 Add the ReactiveFormsModule. Webstorm did this for me
This solves Can't bind to 'formControl' since it isn't a known property of 'input'.
2 Now add the DateFilterComponent made by @DanishAbsar. I did not make any changes to it.
import {Component, OnChanges, OnInit, SimpleChanges} from '@angular/core';
import { FormControl } from '@angular/forms';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
import { DefaultFilter } from 'ng2-smart-table';
@Component({
template: `
<input nbInput placeholder="{{column.title}}" [formControl]="inputControl" [nbDatepicker]="rangepicker">
<nb-rangepicker #rangepicker></nb-rangepicker>
`,
})
export class DateFilterComponent extends DefaultFilter implements OnInit, OnChanges {
inputControl = new FormControl();
constructor() {
super();
}
ngOnInit() {
this.inputControl.valueChanges
.pipe(
distinctUntilChanged(),
debounceTime(this.delay),
)
.subscribe((value: string) => {
if(this.inputControl.status === 'VALID')
{
this.query = value !== null ? JSON.stringify(this.inputControl.value) : "";
this.setFilter();
}
});
}
ngOnChanges(changes: SimpleChanges) {
if (changes.query) {
this.query = changes.query.currentValue;
this.inputControl.setValue(this.inputControl.value);
}
}
}
3 Now add the filter to the settings of your ng-smart-table. Here is a fix I made on the working code of @DanishAbsar. I fixed the filterFunction. I use DateTime from luxon
date: {
title: 'Date',
type: 'string',
filter: {
type: 'custom',
component: DateFilterComponent
},
filterFunction: (value, query) => {
const range = JSON.parse(query)
const start = DateTime.fromISO(range.start)
const end = DateTime.fromISO(range.end)
const date = DateTime.fromISO(value)
return start <= date && date <= end
},
}
Thanks @DanishAbsar for bootstrapping my solution. This was highly helpful!
@snorberhuis sorry men, can you put it in stackblitz?
@DanishAbsar thanks for the code, but it does not work and I dont get any error. Can you put it in stackblitz ?
I have the example of @DanishAbsar working:
1 Add the
ReactiveFormsModule. Webstorm did this for meThis solves
Can't bind to 'formControl' since it isn't a known property of 'input'.2 Now add the DateFilterComponent made by @DanishAbsar. I did not make any changes to it.
import {Component, OnChanges, OnInit, SimpleChanges} from '@angular/core'; import { FormControl } from '@angular/forms'; import { debounceTime, distinctUntilChanged } from 'rxjs/operators'; import { DefaultFilter } from 'ng2-smart-table'; @Component({ template: ` <input nbInput placeholder="{{column.title}}" [formControl]="inputControl" [nbDatepicker]="rangepicker"> <nb-rangepicker #rangepicker></nb-rangepicker> `, }) export class DateFilterComponent extends DefaultFilter implements OnInit, OnChanges { inputControl = new FormControl(); constructor() { super(); } ngOnInit() { this.inputControl.valueChanges .pipe( distinctUntilChanged(), debounceTime(this.delay), ) .subscribe((value: string) => { if(this.inputControl.status === 'VALID') { this.query = value !== null ? JSON.stringify(this.inputControl.value) : ""; this.setFilter(); } }); } ngOnChanges(changes: SimpleChanges) { if (changes.query) { this.query = changes.query.currentValue; this.inputControl.setValue(this.inputControl.value); } } }3 Now add the filter to the settings of your
ng-smart-table. Here is a fix I made on the working code of @DanishAbsar. I fixed the filterFunction. I useDateTimefrom luxondate: { title: 'Date', type: 'string', filter: { type: 'custom', component: DateFilterComponent }, filterFunction: (value, query) => { const range = JSON.parse(query) const start = DateTime.fromISO(range.start) const end = DateTime.fromISO(range.end) const date = DateTime.fromISO(value) return start <= date && date <= end }, }Thanks @DanishAbsar for bootstrapping my solution. This was highly helpful!
Hi @snorberhuis, thanks a lot for the explanation, but I couldn't manage it to work, could you please provide us a stackblitz example? I would really appreciate it.
const start = DateTime.fromISO(range.start) const end = DateTime.fromISO(range.end)
const date = DateTime.fromISO(value) return start <= date && date <= end
Hi, I just found out why it was not working.
Since value is an array, you have to change this row: const date = DateTime.fromISO(value[0]);
I'm using the dayjs library here, and it worked pretty smoothly. Using dayjs:
filterFunction: (value, query) => {
const range = JSON.parse(query);
const rowDate = value[0];
return dayjs(range.start).isSameOrBefore(rowDate) && dayjs(rowDate).isSameOrBefore(range.end);
},
Hi, This may help Someone. I am attaching the code here.
1. below is the code I create as a separate component and render in the smart table filter.
import { Component, EventEmitter, OnChanges, Output, SimpleChanges, ViewChild } from '@angular/core';
import * as moment from 'moment';
import { DefaultFilter } from 'ng2-smart-table';
import { DaterangepickerDirective } from 'ngx-daterangepicker-material';
@Component({
selector: 'datepicker-range',
template:
<input class="form-control py-2 border-right-0 border search-box" type="text" name="focus" #rangerpicker placeholder="Date Range Filter..." (change)="choosedDate($event)" [locale]="{applyLabel: 'Apply',format: 'DD/MM/YYYY'}" [ranges]="ranges" [showDropdowns]="true" [(ngModel)]="selected" [showCustomRangeLabel]="true" [alwaysShowCalendars]="true" ngxDaterangepickerMd required > <button class="close-icon" type="button" (click)="clearrecord($event)"></button> ,
styles: [.search-box,.close-icon{ position: relative; } button{ position: relative; } :host::ng-deep div.md-drppicker { position: fixed; font-family: Roboto,sans-serif; color: green; border-radius: 4px; padding: 4px; overflow: hidden; z-index: 1; font-size: 14px; background-color: #fff; } .close-icon { border:1px solid transparent; background-color: transparent; display: inline-block; vertical-align: middle; outline: 0; cursor: pointer; position: absolute; } .close-icon:after { content: "X"; display: block; width: 30px; height: 34px; position: absolute; background-color: #007bff; z-index: 1; right: -145px; top: -35px; bottom: 0; margin: 0px 43px 0px 0px; padding: 6px; color: black; font-weight: normal; font-size: 12px; cursor: pointer; } @media only screen and (max-device-width: 480px) { .close-icon:after { content: "X"; display: block; width: 20px; height: 32px; position: absolute; background-color: #007bff; z-index: 1; right: -48px; top: -37px; bottom: 0; margin: auto; padding: 6px; color: black; font-weight: normal; font-size: 12px; cursor: pointer; } } .search-box:not(:valid) ~ .close-icon { display: none; } ]
})
export class DatepickerRangeComponent extends DefaultFilter implements OnChanges {
@ViewChild(DaterangepickerDirective, { static: true }) picker: DaterangepickerDirective;
@Output() filter: EventEmitter
ngOnChanges(changes: SimpleChanges) {
if (changes.query) {
this.query = changes.query.currentValue;
}
}
choosedDate(event) {
var startDate = new Date(moment(event.startDate).format('YYYY-MM-DD')).getTime();
var endDate = new Date(moment(event.endDate).format('YYYY-MM-DD'));
endDate.setHours(23, 59, 59, 999)
var searchDate = startDate + '-' + endDate.getTime();
this.filter.emit(searchDate);
}
clearrecord(event) {
this.picker.clear();
this.filter.emit(event);
}
}
2. add filter emitter in Html and called in ts file like point 3.
<ng2-smart-table [settings]="settings" [source]="source" (filter)="filterDateRange($event)">
3. add the filter function like below, UploadDate: { title: 'Uploaded Date', sort: true, sortDirection: 'desc', valuePrepareFunction: (UploadDate: Date) => { return this.datePipe.transform(UploadDate, 'dd/MM/yyyy'); }, filter: { type: 'custom', component: DatepickerRangeComponent }, filterFunction: (cell?: any, search?: string) => { if (search.length > 0) { const dates = search.split('-'); var startDate = parseInt(dates[0]); var endDate = parseInt(dates[1]); var date = new Date(cell).getTime(); return (date >= startDate && date <= endDate); } else return 'N/A'; } }
4. Added screenshot below.
