p-table 过滤器 header 中的 primeng p-calendar,允许使用手动输入日期并清除它

primeng p-calendar in p-table filter header, allow use to enter date manually and clear it

我在 table 的 header 中使用 primeng 的 p-calendar 作为过滤器。我需要 select 一个日期,但也需要手动输入一个日期,因此必须使用 handleSelection 方法实现一个 injectable 服务。丑陋的问题是我目前必须 return 当前 selectedValue 并将其分配给前一个。

有没有办法将 previousStartDate(日期类型)作为参考传递,这样我就可以在 handleSelection 函数中更新它而不是 return是吗?

<p-calendar #startDate appendTo="body" dateFormat="dd M yy" 
    (onSelect)="previousStartDate = calendarService.handleSelection(dt, startDate, 'startDate', 'equals', previousStartDate)" 
    (onBlur)="previousStartDate = calendarService.handleSelection(dt, startDate, 'startDate', 'equals', previousStartDate)"
    styleClass="sym-column-filter">
</p-calendar>

我的 handleSelection 函数如下所示

@Injectable({
    providedIn: 'root'
})
export class CalendarService {

    constructor(private dateService: DateService) {}

    /*
    To be used for the p-table filters where the filter is a p-calendar
    This allows us to also enter the date manually in the text box
    */
    handleSelection(dt: Table, calendar: Calendar, field: string, comparisonMethod: string, previousDate: Date | null): Date | null {
        // only continue if the value has changed from the previous one
        if (calendar.value === previousDate) {
            return;
        }
        // If there is a date then filter by that
        if (calendar.value) {
            dt.filter(this.dateService.formatDate(calendar.value), field, comparisonMethod);
        } else {
            // Otherwise we may have removed some text so need to refresh the p-table
            dt.filter('', field, comparisonMethod);
        }
        return calendar.value;
    }
}

只是拍一张它的样子

我玩了更多,发现了另一种方法,实际上更简单。而不是使用 onSelectonBlur 我发现你可以使用 ngModelChange 调用。

在 p-table header 中使用 p-calendar 似乎有一些限制,尤其是当您想在 select 中输入日期时(现有最常见的方法)。对我来说,我想输入文本,但也希望它在清除(无值)时发出过滤请求。这种方法就是这样做的,它会忽略无效日期,但会在它为空或具有有效日期时发出请求。

标记如下:

<p-calendar
    #endDate 
    [(ngModel)]="endDateFilter" 
    (ngModelChange)="calendarService.calendarDateChanged($event, endDate, dt, 'endDate', 'equals')" 
    appendTo="body" 
    dateFormat="dd M yy" 
    placeholder="Select"                        
    styleClass="sym-column-filter">
</p-calendar>

现在我的助手服务看起来像这样:

import { Injectable } from '@angular/core';
import { Calendar } from 'primeng/calendar';
import { Table } from 'primeng/table';
import { DateService } from './date.service';

/**
 * The calendar helper service is a common injectable service that can handle entering a date in the p-calendar when the p-calendar
 * is used as a filter header
 */
@Injectable({
    providedIn: 'root'
})
export class CalendarService {

    constructor(private dateService: DateService) {}

    /*
    To be used for the p-table filters where the filter is a p-calendar
    This allows us to also enter the date manually in the text box
    */
    calendarDateChanged(calendarDate: Date | null, calendar: Calendar, table: Table, field: string, comparisonMethod: string) {
        // We do a setTimeout to give it one tick of time to make sure the selected date is populated
        // If we don't do this then the date will be an empty string even though they may have selected a date
        setTimeout(() => {
            // Get the DOM input field to check the text, this is primarily to check of the value has been cleared
            // so we need to reset the filter
            const calendarInput = calendar?.el.nativeElement.querySelector('input');
            if (calendarInput) {
                const enteredValue = calendarInput.value;
                // check it is a valid date or is empty for clearing the filter
                if (calendarDate || enteredValue === '') {
                    table.filter(enteredValue === '' ? null : this.dateService.formatDate(calendar.value), field, comparisonMethod);
                }
            }
        }, 1);
      }
}

然后我可以通过将它作为服务注入来在我的组件中使用它,必须使其成为 public 以便标记调用它。

endDateFilter: Date | null;

constructor(
    public calendarService: CalendarService
) { }