Reputation: 13
I have an issue with creating date filter on kendo Ui grid angular 2 integration component. the problem is I want to filter a date column in between two specific dates I mean a date range. I searched the forums of Kendo and also Stackoverflow but I haven't found anything. so does anybody have the same experience on filtering date column between two dates in Kendo ui grid angular 2 components. I would really appreciated if you can make an example on this issue. Thanks everyone.
Upvotes: 1
Views: 2821
Reputation: 103
It would be great to see your code to determine exactly the answer to your specific case.
Anyway, I created a grid for my employer with the functionality you want with the kendo components out of the box. My project is using angular 4, typescript 2.9 and WEB API with OData v4.
The only workaround in my specific case was handling timestamps. At the time of this answer, Kendo grids do not play well with timestamps other than midnight.
Here is the component.html:
**Notice that setting filterable="menu"
on the kendo-grid
tag and filter="date"
in the date columns is one official way to setup date filtering as per kendo's docs. then you can use format=""
to set your desired date format
<kendo-grid [filter]="GridState.filter" filterable="menu" (filterChange)="filterChange($event)" [data]="gridData(list)" [pageSize]="GridState.take"
(dataStateChange)="onStateChange($event)" [skip]="GridState.skip" [sort]="GridState.sort" [sortable]="true" [pageable]="true"
(sortChange)="sortChange($event)" [scrollable]="'none'">
<kendo-grid-column field="ReturnStatusDisplay" title="Status" width="columnWidth">
</kendo-grid-column>
<kendo-grid-column field="Preparer.Id" title="Preparer Id" width="columnWidth" filter="numeric" format="{0:d}">
</kendo-grid-column>
<kendo-grid-column field="ReceivedDate" title="Received Date" width="columnWidth" filter="date" format="{0:MM/dd/yyyy}">
</kendo-grid-column>
<kendo-grid-column field="AdmCreatedDate" title="Processed Date" width="columnWidth" filter="date" format="{0:MM/dd/yyyy}">
</kendo-grid-column>
</kendo-grid>
To properly handle the time stamps I created a method on the typescript to set all timestamps to the nearest midnight
public setTimestampToNearestMidnight(entitySet: any[], dateProperty): any[] {
entitySet.forEach(e => {
let dateWithNearestMidnight = new Date(e[dateProperty]).setHours(0,0,0,0);
e[dateProperty] = new Date(dateWithNearestMidnight);
})
return entitySet;
}
Then apply it to the list of objects that I need to display
public get ReturnsList$(): Observable<Return[]> {
let processedReturnsList: Return[] = this._accountManagementService._companyFolio.Returns;
processedReturnsList = this._commonService.setTimestampToNearestMidnight(processedReturnsList, ReturnDateProperties.ADM_CREATED_DATE);
processedReturnsList = this._commonService.setTimestampToNearestMidnight(processedReturnsList, ReturnDateProperties.RECEIVED_DATE);
processedReturnsList = this.concatenateReturnTypeAndDescription(processedReturnsList);
return Observable.of(processedReturnsList);
}
Do take notice I am using observables as grid data and then the async pipe to subscribe from the HTML.
If timestamps and observables do not apply to you, you can disregard the setTimestampToNearestMidnight()
and ReturnsList$()
part.
As you can see in the screenshot below, you can use the AND operator on the menu to select a range of dates; in this case between 07/31/2018 - 08/29/2018 is the selected range.
I hope this helps!
Upvotes: 2
Reputation: 123
I am using the Kendo UI Grid for Angular. Angular version is 5 using TypeScript.
The main issue is that the grid renders date as string, and when the date filter is applied, it tries to compare a string type with a Date type which is just inherently incompatible.
To circumvent this issue, I use the moment.js library which can convert strings to date format, or date to string format for comparison between the two.
Make sure you have referenced momentjs properly in your project. Add this to your component.ts (outside the class export, because following is pure javascript code).
class Range {
from: Date;
to: Date;
}
// Custom Filter Operator: isWithin
function isWithin(columnValue: Date, range: Range): boolean {
if (columnValue) {
return moment(columnValue).isBetween(moment(range.from), moment(range.to), 'minute', '[]');
} else {
return false;
}
}
The following is the typescript code in the component.ts which basically adds custom filters to the Kendo Grid's filter. The onMinDateChange and onMaxDateChange functions are called whenever value in the Date Pickers are updated (see the component.html's code), and the filters are updated automatically.
public onMinDateChange(value: Date): void {
this.filterDateRange(value, this.filterValueDateMax);
}
public onMaxDateChange(value: Date): void {
this.filterDateRange(this.filterValueDateMin, value);
}
public filterDateRange(min, max): void {
this.filter.filters = [];
if (min && max) {
this.filter.filters.push({
field: this.field,
operator: isWithin,
value: { from: min, to: max }
});
}
}
The filter is input by adding this line in the component.ts:
@Input() public filter: CompositeFilterDescriptor;
The date-time picker (you can use just the date picker if you want) is defined in the component.html something along the following lines:
<div class="row">
<kendo-datepicker [(value)]="filterValueDateMin" [format]="'MM/dd/yyyy HH:mm:ss'" (valueChange)="onMinDateChange($event)"> </kendo-datepicker>
<kendo-timepicker [(value)]="filterValueDateMin" (valueChange)="onMinDateChange($event)"> </kendo-timepicker>
</div>
<div class="row">
<kendo-datepicker [(value)]="filterValueDateMax" [format]="'MM/dd/yyyy HH:mm:ss'" (valueChange)="onMaxDateChange($event)"> </kendo-datepicker>
<kendo-timepicker [(value)]="filterValueDateMax" (valueChange)="onMaxDateChange($event)"> </kendo-timepicker>
</div>
Finally, this is how I am using the filter in the main grid's html:
<ng-template kendoGridFilterMenuTemplate *ngIf="col.fieldName === 'insertFieldNameHere'"
let-filter="filter"
let-column="column"
let-filterService="filterService">
<app-date-time-range-filter [headerTitle]="col.displayName"
[filter]="filter"
[field]="column.field">
</app-date-time-range-filter>
</ng-template>
Hope this helps.
Upvotes: 1