如何让Kendo React UI DataTable实现jQuery版弹窗筛选交互?
Got it, let's walk through how to get that jQuery Kendo UI-style filter popup working in Kendo React DataTable. Here's a straightforward, step-by-step approach you can implement:
1. Build a Custom Header Component with Filter Button & Popup
First, we'll create a reusable header component that includes a filter button and a popup for filter controls. This replaces the default inline filter row:
import { Button } from '@progress/kendo-react-buttons'; import { Popup } from '@progress/kendo-react-popup'; const CustomFilterHeader = ({ column, filter, onFilterChange, isPopupOpen, togglePopup }) => { const handleClearFilter = () => { onFilterChange(null); togglePopup(); }; const handleApplyFilter = () => { togglePopup(); }; return ( <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 8px' }}> <span>{column.title}</span> <Button icon="filter" onClick={togglePopup} size="small" /> {isPopupOpen && ( <Popup anchor={{ current: document.querySelector(`[data-column="${column.field}"]`) }} position="bottom start" onClose={togglePopup} modal={false} > <div style={{ padding: '16px', backgroundColor: '#fff', border: '1px solid #e0e0e0', borderRadius: '4px', minWidth: '200px' }}> <h5 style={{ margin: '0 0 12px 0', fontSize: '14px' }}>Filter {column.title}</h5> {/* Example: Text input for string filters */} {column.field !== 'age' && ( <input type="text" placeholder="Enter value..." value={filter?.value || ''} onChange={(e) => { onFilterChange({ field: column.field, operator: 'contains', value: e.target.value }); }} style={{ width: '100%', padding: '6px', marginBottom: '12px', border: '1px solid #eee' }} /> )} {/* Example: Numeric input for number fields */} {column.field === 'age' && ( <input type="number" placeholder="Enter age..." value={filter?.value || ''} onChange={(e) => { onFilterChange({ field: column.field, operator: 'eq', value: parseInt(e.target.value) || '' }); }} style={{ width: '100%', padding: '6px', marginBottom: '12px', border: '1px solid #eee' }} /> )} <div style={{ display: 'flex', gap: '8px', justifyContent: 'flex-end' }}> <Button size="small" onClick={handleClearFilter}>Clear</Button> <Button size="small" themeColor="primary" onClick={handleApplyFilter}>Apply</Button> </div> </div> </Popup> )} </div> ); };
2. Integrate the Custom Header with Your DataTable
Next, wire up this custom header to your DataTable columns, and manage the popup state for each column individually (so multiple filters don't conflict):
import { useState } from 'react'; import { DataTable, Column } from '@progress/kendo-react-data-grid'; import { process } from '@progress/kendo-data-query'; const AppDataTable = ({ initialData }) => { const [filter, setFilter] = useState(null); // Track popup open state per column using an object const [popupOpenStates, setPopupOpenStates] = useState({}); const handleFilterChange = (newFilter) => { setFilter(newFilter); }; const toggleColumnPopup = (field) => { setPopupOpenStates(prev => ({ ...prev, [field]: !prev[field] })); }; // Process data with the current filter const filteredData = process(initialData, { filter }).data; return ( <DataTable data={filteredData}> <Column field="name" title="Full Name" headerCell={(props) => ( <CustomFilterHeader {...props} filter={filter} onFilterChange={handleFilterChange} isPopupOpen={popupOpenStates.name || false} togglePopup={() => toggleColumnPopup('name')} /> )} data-column="name" /> <Column field="age" title="Age" headerCell={(props) => ( <CustomFilterHeader {...props} filter={filter} onFilterChange={handleFilterChange} isPopupOpen={popupOpenStates.age || false} togglePopup={() => toggleColumnPopup('age')} /> )} data-column="age" /> <Column field="email" title="Email" /> {/* Add more columns as needed */} </DataTable> ); };
3. Add Advanced Filter Options (Optional)
If you want to match the jQuery version's flexibility (like multiple filter operators), add a dropdown to select operators in the popup:
// Inside the CustomFilterHeader's popup content <select value={filter?.operator || 'contains'} onChange={(e) => { onFilterChange({ ...filter, operator: e.target.value }); }} style={{ width: '100%', padding: '6px', marginBottom: '12px', border: '1px solid #eee' }} > <option value="contains">Contains</option> <option value="eq">Equals</option> <option value="gt">Greater Than</option> <option value="lt">Less Than</option> </select>
4. Tweak Styles for a Polished Look (Optional)
Add some custom CSS to make the popup and button feel more like the jQuery Kendo UI version:
.k-button[icon="filter"] { opacity: 0.7; } .k-button[icon="filter"]:hover { opacity: 1; } .k-popup-content { box-shadow: 0 4px 12px rgba(0,0,0,0.15); }
This setup will give you a filter button in each column header that opens a popup for filter controls, just like the jQuery Kendo UI implementation.
内容的提问来源于stack exchange,提问作者Vencovsky

