问题
How to sort a date column based on the date range? Angular material data table. I am working a project now facing a problem on how to date column sort data based on the date range fromDate and toDate using with filterPredicate or any other option in mat-table.
The date column will be shown in between date range. Please refer screenshot and look at the project in stackblitz here
https://stackblitz.com/edit/angular-pkkvbd-cdtxwz-date-range-filter?embed=1&file=app/table-filtering-example.ts
If I selected 1 Jan 2019 to 31 Dec 2020 the data will be shown all the between date results
回答1:
TL;DR: https://stackblitz.com/edit/angular-pkkvbd-cdtxwz-date-range-filter-jzlwxr?file=app/table-filtering-example.ts
You want to not only sorting but also filtering your table. These are separated concerns in angular material, considering you are using angular material. You will have to provide the filtering components first and use that data to implement a filterPredicate function manually, yes manually.
Filtering:
export class TableFilteringExample {
displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
dataSource = new MatTableDataSource(ELEMENT_DATA);
applyFilter(filterValue: string) {
this.dataSource.filterPredicate = filterPeriod;
}
filterPeriod(data: T, filter: string) {
return data.referenceDate > startDateFilter.value() && data.referenceDate < endDateFilter.value();
}
}
Sorting functions are also available for your material.table component, but this component comes out-of-the-box for you. Refer to https://material.angular.io/components/table/overview#sorting on how to use the MatSort component properly:
<table mat-table [dataSource]="dataSource" matSort class="mat-elevation-z8">
...
then, in your .ts
component, you will refer to the matSort as:
@ViewChild(MatSort, {static: true}) sort: MatSort;
You need to complete several steps if you want to complete the story and a lettle of reading to understand how to adapt the material components to your case. I suggest you to start your jorney here https://material.angular.io/components/table/overview#sorting
回答2:
In order to achieve your expected result, you need to change the dataSource
type. Also you need a method to rebuild your array of items based on the user's date range selection.
Your xxx.component.ts
should look like this.
import { Component } from '@angular/core';
import { MatTableDataSource } from '@angular/material';
import { DatePipe } from '@angular/common';
import {FormControl, FormGroup} from '@angular/forms';
import * as moment from 'moment';
export interface PeriodicElement {
name: string;
position: number;
weight: number;
DOB: Date;
created: Date;
}
const ELEMENT_DATA: PeriodicElement[] = [
{ position: 1, name: 'Hydrogen', weight: 1.0079, DOB: new Date(2016, 11, 24), created: new Date(2015, 15, 24) },
{ position: 2, name: 'Helium', weight: 4.0026, DOB: new Date(2018, 18, 24), created: new Date(2018, 11, 24) },
{ position: 3, name: 'Lithium', weight: 6.941, DOB: new Date(1993, 6, 12), created: new Date(1999, 12, 15) },
{ position: 4, name: 'Beryllium', weight: 9.0122, DOB: new Date(2001, 7, 6), created: new Date(2011, 10, 6) },
{ position: 5, name: 'Boron', weight: 10.811, DOB: new Date(2020, 5, 9), created: new Date(2020, 5, 9) },
{ position: 6, name: 'Carbon', weight: 12.0107, DOB: new Date(2008, 7, 14), created: new Date(2008, 7, 14) },
{ position: 7, name: 'Nitrogen', weight: 14.0067, DOB: new Date(1998, 11, 18), created: new Date(1998, 11, 18) },
{ position: 8, name: 'Oxygen', weight: 15.9994, DOB: new Date(2002, 2, 24), created: new Date(2002, 2, 24) },
{ position: 9, name: 'Fluorine', weight: 18.9984, DOB: new Date(2006, 4, 29), created: new Date(2006, 4, 29) },
{ position: 10, name: 'Neon', weight: 20.1797, DOB: new Date(2040, 5, 30), created: new Date(2040, 5, 30) },
];
/**
* @title Table with filtering
*/
@Component({
selector: 'table-filtering-example',
styleUrls: ['table-filtering-example.css'],
templateUrl: 'table-filtering-example.html',
})
export class TableFilteringExample {
displayedColumns: string[] = ['position', 'name', 'weight', 'DOB', 'founded'];
dataSource = ELEMENT_DATA;
pipe: DatePipe;
filterForm = new FormGroup({
fromDate: new FormControl(),
toDate: new FormControl(),
});
get fromDate() { return this.filterForm.get('fromDate'); }
get toDate() { return this.filterForm.get('toDate'); }
constructor() {
}
getDateRange(value) {
// getting date from calendar
const fromDate = value.fromDate
const toDate = value.toDate
const tempData = <any>this.dataSource;
let selectedItems: PeriodicElement[] = [];
if(fromDate !== '' && toDate !== '') {
tempData.forEach((item, index) => {
if (item.DOB >= fromDate && item.DOB <= toDate) {
selectedItems.push(item);
}
});
this.dataSource = selectedItems;
}
}
applyFilter(filterValue: string) {
// this.dataSource.filter = filterValue.trim().toLowerCase();
}
}
回答3:
You can use filter function.
getDateRange(value) {
this.dataSource.data = ELEMENT_DATA;
const fromDate = value.fromDate
const toDate = value.toDate
this.dataSource.data = this.dataSource.data.filter(e=>e.DOB > fromDate && e.DOB < toDate ) ;
}
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
More information about filter function
Stackblitz example based on your example.
来源:https://stackoverflow.com/questions/55517077/angular-material-data-table-column-sort-by-date-range