Let’s look at how to implement Angular selection range for the newest Angular PrimeNg version. This tutorial was developed on v10.0.0-rc-1 version.
I had difficulty to find a proper solution for range selection in PrimeNg turbo data table for the newest version. Therefore I have decided to create a workaround. For the time selection, each click event on the calendar panel fire only one piece of data – currently selected date. So the calendar range is stateless. You need to remember somehow keep in memory what date was fired before and implement this logic in a custom filter.
I observed that there are several rules according to which p-calendar
component behave when the selection mode "range"
is selected. Here are my findings according to which I programmed the logic:
- At first, the calendar component has an empty, undefined selection.
- If one date is selected, only one date is fired on click event.
- If the same date as date previously selected is selected, new date (which is the same as previously selected date) is fired on click event.
- If a date before the already selected date is selected, the selection is cancelled and earlier date is fired on click event.
- If a date after the already selected date is selected, the selection range is visible.
- If any new date is selected after the selection range is visible, a new date is selected, fired upon click event and selection range is cancelled.
When all this wrote down here is implementation code for component and custom filter:
record-list.component.html
<p-table #dt [value]="records" sortMode="multiple" [paginator]="true" [rowsPerPageOptions]="rowsPerPageTable" [rows]="rowsPerTable" [showCurrentPageReport]="true" [(first)]="page" styleClass="p-datatable-striped" currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries"> <ng-template pTemplate="header"> <tr class="ui-table-thead"> <th [ngStyle]="{'width':'50%'}" pSortableColumn="createdDate">Created <p-sortIcon field="createdDate"></p-sortIcon></th> <th [ngStyle]="{'width':'50%'}" pSortableColumn="info">Info <p-sortIcon field="info"></p-sortIcon></th> </tr> <tr class="ui-table-thead"> <th> <p-calendar (onSelect)="onDateSelect($event)" [style]="{'width':'100%'}" selectionMode="range" [readonlyInput]="true" (onClearClick)="onDateClear($event)" [showButtonBar]="true" placeholder="Created Date" class="p-column-filter" dateFormat="yy-mm-dd"></p-calendar> </th> <th> <input pInputText type="text" [style]="{'width':'100%'}" (input)="dt.filter($event.target.value, 'info', 'contains')" placeholder="Info"> </th> </tr> </ng-template> <ng-template pTemplate="body" let-rowData> <tr ng-repeat="rowData in let-rowData" ng-click="showClient(rowData)"> <td>{{ rowData.createdDate }}</td> <td>{{ rowData.info }}</td> </tr> </ng-template> </p-table>
record-list.component.ts
export class RecordListComponent implements OnInit { public records: IssueShortInfo[]; @ViewChild('dt') table: Table; cols: any[]; dateRangeStart: string; dateRangeEnd: string; rowsPerPageTable: number[] = [25, 50, 100, 200]; page: number = 0; rowsPerTable: number = 25; constructor(private recordService: RecordService) {} ngOnInit() { this.recordService.getAllRecords().subscribe(page => { this.getRecords(page); }, (error => { console.log(error) })); this.cols = [ {field: 'id', header: 'Id'}, {field: 'createdDate', header: 'Created Date'}, {field: 'info', header: 'Info'} ]; FilterUtils['customCreatedDateFilter'] = (value: string, filter) => { if (this.dateRangeStart === value && this.dateRangeEnd === undefined) { return true; } if (this.dateRangeStart === value || this.dateRangeEnd === value) { return true; } if ( this.dateRangeStart !== undefined && this.dateRangeEnd !== undefined && moment(this.dateRangeStart).isBefore(value) && moment(this.dateRangeEnd).isAfter(value)) { return true; } return false; }; } getRecords(page: Page) { this.records = page.content.map(incomingRecordDTO => new Record(incomingRecordDTO)); } onDateSelect($event) { const eventDate = this.formatDate($event); if (this.dateRangeStart === undefined) { this.dateRangeStart = eventDate; } else if (moment($event).isBefore(this.dateRangeStart)) { this.dateRangeStart = eventDate; this.dateRangeEnd = undefined; } else if (moment($event).isSame(this.dateRangeStart) && this.dateRangeStart !== undefined && this.dateRangeEnd === undefined) { this.dateRangeEnd = eventDate; } else if (moment($event).isSame(this.dateRangeStart) && this.dateRangeStart !== undefined && this.dateRangeEnd !== undefined) { this.dateRangeStart = eventDate; this.dateRangeEnd = undefined; } else if (moment($event).isAfter(this.dateRangeStart) && this.dateRangeStart !== undefined && this.dateRangeEnd !== undefined) { this.dateRangeStart = eventDate; this.dateRangeEnd = undefined; } else { this.dateRangeEnd = eventDate; } this.table.filter(eventDate, 'createdDate', 'customCreatedDateFilter'); } onDateClear($event) { this.dateRangeStart = undefined; this.dateRangeEnd = undefined; this.table.filter('', 'createdDate', 'equals'); } formatDate(date) { let month = date.getMonth() + 1; let day = date.getDate(); if (month < 10) { month = '0' + month; } if (day < 10) { day = '0' + day; } return date.getFullYear() + '-' + month + '-' + day; } customCreatedDateArrayFilter(event) { this.table.filter(event, 'createdDate', 'customCreatedDateFilter'); } }
Thanks for sharing, I was looking for a solution like this