iT邦幫忙

2024 iThome 鐵人賽

DAY 21
0
Modern Web

關於寫react 那二三事系列 第 21

Day 21 PrimeReact的 tables (11)

  • 分享至 

  • xImage
  •  

好了來到 DataTable 最後一哩,
之後看看TreeTable等,用法上感覺大同小異

關於FilterOperator

  1. FilterOperator.AND
    =>多個過濾條件中所有條件都成立才成立
  2. FilterOperator.OR
    =>多個過濾條件中當其中任意一個條件成立便會成立

關於FilterMatchMode
1.FilterMatchMode.CONTAINS
=> 檢查字段值是否包含指定的子字符串。
2.FilterMatchMode.STARTS_WITH
=>檢查字段值是否以指定的子字符串開頭。
3.FilterMatchMode.ENDS_WITH
=>檢查字段值是否以指定的子字符串結尾。
4.FilterMatchMode.EQUALS
=>檢查字段值是否等於指定值。
5.FilterMatchMode.NOT_EQUALS
=>檢查字段值是否不等於指定值。
6. FilterMatchMode.IN
=>檢查字段值是否存在於指定值的集合中。
7.FilterMatchMode.LESS_THAN
=>檢查字段值是否小於指定值。
8.FilterMatchMode.LESS_THAN_OR_EQUAL
=>檢查字段值是否小於或等於指定值。(與 LESS_THAN 類似,但包含等於)
9.FilterMatchMode.GREATER_THAN
=>檢查字段值是否大於指定值。
10.FilterMatchMode.GREATER_THAN_OR_EQUAL
=>檢查字段值是否大於或等於指定值。(與 GREATER_THAN 類似,但包含等於)
11.FilterMatchMode.BETWEEN
=>檢查字段值是否在兩個值之間(包含邊界值)。
12.FilterMatchMode.IS
=>檢查字段值是否等於指定值(類似於 EQUALS 但用於簡單的等值匹配)。
13. FilterMatchMode.IS_NOT
=>檢查字段值是否不等於指定值(類似於 NOT_EQUALS)。
14.FilterMatchMode.EMPTY
=>檢查字段值是否為空(空字符串或 null)。
15.FilterMatchMode.NOT_EMPTY
=>檢查字段值是否不為空(非空字符串或非 null)。

那麼上全Code

import React, { useState, useEffect } from 'react';
import { FilterMatchMode, FilterOperator } from 'primereact/api';
import { DataTable, DataTableFilterMeta } from 'primereact/datatable';
import { Column, ColumnFilterElementTemplateOptions } from 'primereact/column';
import { InputText } from 'primereact/inputtext';
import { IconField } from 'primereact/iconfield';
import { InputIcon } from 'primereact/inputicon';
import { InputNumber, InputNumberChangeEvent } from 'primereact/inputnumber';
import { Button } from 'primereact/button';
import { ProgressBar } from 'primereact/progressbar';
import { Calendar} from 'primereact/calendar';
import { Slider, SliderChangeEvent } from 'primereact/slider';
import { CustomerService } from '../service/custom';
import { Customer} from '../interfaces/table';

const defaultFilters: DataTableFilterMeta = {
  global: { value: null, matchMode: FilterMatchMode.CONTAINS },
  name: {
    operator: FilterOperator.AND,
    constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }],
  },
  'country.name': {
    operator: FilterOperator.AND,
    constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }],
  },
  date: {
    operator: FilterOperator.AND,
    constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }],
  },
  balance: {
    operator: FilterOperator.AND,
    constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }],
  },
  activity: { value: null, matchMode: FilterMatchMode.BETWEEN },
};

const Tables11Compnent: React.FC = () => {
  const [customers, setCustomers] = useState<Customer[]>([]);
  const [filters, setFilters] = useState<DataTableFilterMeta>(defaultFilters);
  const [loading, setLoading] = useState<boolean>(false);
  const [globalFilterValue, setGlobalFilterValue] = useState<string>('');

  useEffect(() => {
    CustomerService.getCustomersMedium().then((data: Customer[]) => {
      setCustomers(getCustomers(data));
      setLoading(false);
    });
    initFilters();
  }, []);

  const getCustomers = (data: Customer[]) => {
    return [...(data || [])].map((d:any) => {
      d.date = new Date(d.date);
      return d;
    });
  };

  const formatDate = (value: Date) => {
    return value.toLocaleDateString('zh-cn', {
      year: 'numeric',
      month: '2-digit',
      day: '2-digit'
    });
  };

  const formatCurrency = (value: number) => {
    return value.toLocaleString('zh-cn', { style: 'currency', currency: 'TWD' });
  };

  const clearFilter = () => {
    initFilters();
  };

  const onGlobalFilterChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value;
    let _filters:{[key:string]:any} = { ...filters };

    _filters['global'].value = value;

    setFilters(_filters);
    setGlobalFilterValue(value);
  };

  const initFilters = () => {
    setFilters(defaultFilters);
    setGlobalFilterValue('');
  };

  const renderHeader = () => {
    return (
      <div className="flex justify-content-between">
        <Button type="button" icon="pi pi-filter-slash" className="mb-2" label="清除" outlined onClick={clearFilter} />
        <IconField iconPosition="left">
          <InputIcon className="pi pi-search " />
          <InputText style={{paddingLeft:'35px'}} value={globalFilterValue} onChange={onGlobalFilterChange} placeholder="Keyword Search" />
        </IconField>
      </div>
    );
  };

  const countryBodyTemplate = (rowData: Customer) => {
    return (
      <div className="flex align-items-center">
        <span>{rowData.country.name}</span>
      </div>
    );
  };

  const filterClearTemplate = (options:any) => {
    return <Button type="button" icon="pi pi-times" onClick={options.filterCallback} severity="secondary"></Button>;
  };

  const filterApplyTemplate = (options: any) => {
    return <Button type="button" icon="pi pi-check" onClick={options.filterApplyCallback} severity="success"></Button>;
  };

  const filterFooterTemplate = () => {
    return <div className="px-3 pt-0 pb-3 text-center">Filter by Country</div>;
  };

  const dateBodyTemplate = (rowData: Customer) => {
    return formatDate(new Date(rowData.date));
  };

  const dateFilterTemplate = (options: ColumnFilterElementTemplateOptions) => {
    return <Calendar value={options.value} onChange={(e:any) => options.filterCallback(e.value, options.index)} dateFormat="yy/mm/dd" placeholder="yyyy/mm/dd" />;
  };

  const balanceBodyTemplate = (rowData: Customer) => {
    return formatCurrency(rowData.balance);
  };

  const balanceFilterTemplate = (options: ColumnFilterElementTemplateOptions) => {
    return <InputNumber value={options.value} onChange={(e: InputNumberChangeEvent) => options.filterCallback(e.value, options.index)} mode="currency" currency="USD" locale="en-US" />;
  };

  const activityBodyTemplate = (rowData: Customer) => {
    return <ProgressBar value={rowData.activity} showValue={false} style={{ height: '6px' }}></ProgressBar>;
  };

  const activityFilterTemplate = (options: ColumnFilterElementTemplateOptions) => {
    return (
      <React.Fragment>
        <Slider value={options.value} onChange={(e: SliderChangeEvent) => options.filterCallback(e.value)} range className="m-3"></Slider>
        <div className="flex align-items-center justify-content-between px-2">
          <span>{options.value ? options.value[0] : 0}</span>
          <span>{options.value ? options.value[1] : 100}</span>
        </div>
      </React.Fragment>
    );
  };

  const header = renderHeader();

  return (
    <div >
      <DataTable 
         value={customers} loading={loading} dataKey="id"
        filters={filters} globalFilterFields={['name', 'country.name', 'representative.name', 'balance', 'status']} header={header}
        emptyMessage="查無資料" onFilter={(e) => setFilters(e.filters)}>
        <Column field="name" header="Name" filter filterPlaceholder="Search by name"  />
        <Column header="Country" filterField="country.name" body={countryBodyTemplate}
          filter filterPlaceholder="Search by country" filterClear={filterClearTemplate}
          filterApply={filterApplyTemplate} filterFooter={filterFooterTemplate} />
        <Column header="Date" filterField="date" dataType="date" body={dateBodyTemplate} filter filterElement={dateFilterTemplate} />
        <Column header="Balance" filterField="balance" dataType="numeric"  body={balanceBodyTemplate} filter filterElement={balanceFilterTemplate} />
        <Column field="activity" header="Activity" showFilterMatchModes={false}  body={activityBodyTemplate} filter filterElement={activityFilterTemplate} />
      </DataTable>
    </div>
  );
}
export default Tables11Compnent;        

那麼明天見


上一篇
Day20 PrimeReact 的tables (10)
下一篇
Day22 Primereact 的Message
系列文
關於寫react 那二三事30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言