如何使用 MUI 数据表使用值而不是自定义主体渲染中的内容进行排序?
How can I sort using MUI Datatable using value, instead of what's in my custom body render?
在实施自定义过滤器选项之前,温度(数字类型)显示为附加了“°C”的字符串,但仍保留该值,因为它能够进行相应排序(升序和下降)。实现自定义过滤器选项后,我无法再根据值进行过滤,但它会根据从 customBodyRender 返回的字符串进行过滤。例如,如果我将最小值指定为 3,则不会返回 20 和 10 之类的值,因为它现在似乎正在按字母数字排序。当我删除 customBodyRender 时,它工作得很好。
如何让 MUI 数据 table 以我想要的方式呈现,同时保留实际值本身的排序?我粘贴了下面的代码。由于我是新手,我会继续做更多的研究并随着时间的推移更新问题。
const columns = [
{name: "Temperature", options:{
filter: true,
customBodyRender: (value) => {
return (value + "° C")
},
filterType: 'custom',
filterList: [],
customFilterListOptions: {
render: value => {
if (value[0] && value[1]) {
return `Min Temp: ${value[0]}, Max Temp: ${value[1]}`;
} else if (value[0]) {
return `Min Temp: ${value[0]}`;
} else if (value[1]) {
return `Max Temp: ${value[1]}`;
}
return false;
},
update: (filterList, filterPos, index) => {
console.log('customFilterListOnDelete: ', filterList, filterPos, index);
if (filterPos === 0) {
filterList[index].splice(filterPos, 1, '');
} else if (filterPos === 1) {
filterList[index].splice(filterPos, 1);
} else if (filterPos === -1) {
filterList[index] = [];
}
return filterList;
},
},
filterOptions: {
names: [],
logic(value, filters) {
if (filters[0] && filters[1]) {
return (value < filters[0]) || value > filters[1];
} else if (filters[0]) {
return value < filters[0];
} else if (filters[1]) {
return value > filters[1];
}
return false;
},
display: (filterList, onChange, index, column) => (
<div>
<FormLabel>Temperature</FormLabel>
<FormGroup row>
<TextField
label="min"
value={filterList[index][0] || ''}
onChange={event => {
filterList[index][0] = event.target.value;
onChange(filterList[index], index, column);
}}
style={{ width: '45%', marginRight: '5%' }}
/>
<TextField
label="max"
value={filterList[index][1] || ''}
onChange={event => {
filterList[index][1] = event.target.value;
onChange(filterList[index], index, column);
}}
style={{ width: '45%' }}
/>
</FormGroup>
</div>
),
},
}}
]
我在你的代码中发现了两个小问题。
第一个:customFilterListOptions
中的渲染函数应该 return 一个字符串或字符串 [](参见文档)。
第二个:在filterOptions
的逻辑函数中,需要先将values
和filters
转换为数字再进行比较。
如果您有任何问题,请告诉我。
这现在可以工作了:
import React from "react";
import ReactDOM from "react-dom";
import MUIDataTable from "mui-datatables";
import { TextField, FormLabel, FormGroup } from "@material-ui/core";
import { toNumber } from "lodash";
import "./styles.css";
const TEMPERATURE_PREFIX = "° C";
function App() {
const columns = [
{
name: "city",
label: "City",
options: {
filter: true,
sort: false
}
},
{
name: "temp",
label: "Temperature",
options: {
sort: true,
customBodyRender: value => {
return value + TEMPERATURE_PREFIX;
},
filter: true,
filterType: "custom",
filterList: [],
customFilterListOptions: {
render: value => {
if (value[0] && value[1]) {
return `Min Temp: ${value[0]}, Max Temp: ${value[1]}`;
} else if (value[0]) {
return `Min Temp: ${value[0]}`;
} else if (value[1]) {
return `Max Temp: ${value[1]}`;
}
return [];
},
update: (filterList, filterPos, index) => {
console.log(
"customFilterListOnDelete: ",
filterList,
filterPos,
index
);
if (filterPos === 0) {
filterList[index].splice(filterPos, 1, "");
} else if (filterPos === 1) {
filterList[index].splice(filterPos, 1);
} else if (filterPos === -1) {
filterList[index] = [];
}
return filterList;
}
},
filterOptions: {
names: [],
logic(value, filters) {
const temperature = toNumber(
value.replace(TEMPERATURE_PREFIX, "")
);
const lower = toNumber(filters[0]);
const upper = toNumber(filters[1]);
if (lower && upper) {
return temperature < lower || temperature > upper;
} else if (lower) {
return temperature < lower;
} else if (upper) {
return temperature > upper;
}
return false;
},
display: (filterList, onChange, index, column) => (
<div>
<FormLabel>Temperature</FormLabel>
<FormGroup row>
<TextField
label="min"
value={filterList[index][0] || ""}
onChange={event => {
filterList[index][0] = event.target.value;
onChange(filterList[index], index, column);
}}
style={{ width: "45%", marginRight: "5%" }}
/>
<TextField
label="max"
value={filterList[index][1] || ""}
onChange={event => {
filterList[index][1] = event.target.value;
onChange(filterList[index], index, column);
}}
style={{ width: "45%" }}
/>
</FormGroup>
</div>
)
}
}
}
];
const data = [
{ city: "Yonkers", temp: 3 },
{ city: "Hartford", temp: 11 },
{ city: "Tampa", temp: 25 },
{ city: "Dallas", temp: 30 }
];
const options = {
filterType: "checkbox"
};
return (
<div className="App">
<MUIDataTable
title={"Employee List"}
data={data}
columns={columns}
options={options}
/>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
在选项中添加下面的代码。
options={{
sort: true,
sortOrder: { name: 'id', direction: 'desc' },
}}
在实施自定义过滤器选项之前,温度(数字类型)显示为附加了“°C”的字符串,但仍保留该值,因为它能够进行相应排序(升序和下降)。实现自定义过滤器选项后,我无法再根据值进行过滤,但它会根据从 customBodyRender 返回的字符串进行过滤。例如,如果我将最小值指定为 3,则不会返回 20 和 10 之类的值,因为它现在似乎正在按字母数字排序。当我删除 customBodyRender 时,它工作得很好。
如何让 MUI 数据 table 以我想要的方式呈现,同时保留实际值本身的排序?我粘贴了下面的代码。由于我是新手,我会继续做更多的研究并随着时间的推移更新问题。
const columns = [
{name: "Temperature", options:{
filter: true,
customBodyRender: (value) => {
return (value + "° C")
},
filterType: 'custom',
filterList: [],
customFilterListOptions: {
render: value => {
if (value[0] && value[1]) {
return `Min Temp: ${value[0]}, Max Temp: ${value[1]}`;
} else if (value[0]) {
return `Min Temp: ${value[0]}`;
} else if (value[1]) {
return `Max Temp: ${value[1]}`;
}
return false;
},
update: (filterList, filterPos, index) => {
console.log('customFilterListOnDelete: ', filterList, filterPos, index);
if (filterPos === 0) {
filterList[index].splice(filterPos, 1, '');
} else if (filterPos === 1) {
filterList[index].splice(filterPos, 1);
} else if (filterPos === -1) {
filterList[index] = [];
}
return filterList;
},
},
filterOptions: {
names: [],
logic(value, filters) {
if (filters[0] && filters[1]) {
return (value < filters[0]) || value > filters[1];
} else if (filters[0]) {
return value < filters[0];
} else if (filters[1]) {
return value > filters[1];
}
return false;
},
display: (filterList, onChange, index, column) => (
<div>
<FormLabel>Temperature</FormLabel>
<FormGroup row>
<TextField
label="min"
value={filterList[index][0] || ''}
onChange={event => {
filterList[index][0] = event.target.value;
onChange(filterList[index], index, column);
}}
style={{ width: '45%', marginRight: '5%' }}
/>
<TextField
label="max"
value={filterList[index][1] || ''}
onChange={event => {
filterList[index][1] = event.target.value;
onChange(filterList[index], index, column);
}}
style={{ width: '45%' }}
/>
</FormGroup>
</div>
),
},
}}
]
我在你的代码中发现了两个小问题。
第一个:customFilterListOptions
中的渲染函数应该 return 一个字符串或字符串 [](参见文档)。
第二个:在filterOptions
的逻辑函数中,需要先将values
和filters
转换为数字再进行比较。
如果您有任何问题,请告诉我。
这现在可以工作了:
import React from "react";
import ReactDOM from "react-dom";
import MUIDataTable from "mui-datatables";
import { TextField, FormLabel, FormGroup } from "@material-ui/core";
import { toNumber } from "lodash";
import "./styles.css";
const TEMPERATURE_PREFIX = "° C";
function App() {
const columns = [
{
name: "city",
label: "City",
options: {
filter: true,
sort: false
}
},
{
name: "temp",
label: "Temperature",
options: {
sort: true,
customBodyRender: value => {
return value + TEMPERATURE_PREFIX;
},
filter: true,
filterType: "custom",
filterList: [],
customFilterListOptions: {
render: value => {
if (value[0] && value[1]) {
return `Min Temp: ${value[0]}, Max Temp: ${value[1]}`;
} else if (value[0]) {
return `Min Temp: ${value[0]}`;
} else if (value[1]) {
return `Max Temp: ${value[1]}`;
}
return [];
},
update: (filterList, filterPos, index) => {
console.log(
"customFilterListOnDelete: ",
filterList,
filterPos,
index
);
if (filterPos === 0) {
filterList[index].splice(filterPos, 1, "");
} else if (filterPos === 1) {
filterList[index].splice(filterPos, 1);
} else if (filterPos === -1) {
filterList[index] = [];
}
return filterList;
}
},
filterOptions: {
names: [],
logic(value, filters) {
const temperature = toNumber(
value.replace(TEMPERATURE_PREFIX, "")
);
const lower = toNumber(filters[0]);
const upper = toNumber(filters[1]);
if (lower && upper) {
return temperature < lower || temperature > upper;
} else if (lower) {
return temperature < lower;
} else if (upper) {
return temperature > upper;
}
return false;
},
display: (filterList, onChange, index, column) => (
<div>
<FormLabel>Temperature</FormLabel>
<FormGroup row>
<TextField
label="min"
value={filterList[index][0] || ""}
onChange={event => {
filterList[index][0] = event.target.value;
onChange(filterList[index], index, column);
}}
style={{ width: "45%", marginRight: "5%" }}
/>
<TextField
label="max"
value={filterList[index][1] || ""}
onChange={event => {
filterList[index][1] = event.target.value;
onChange(filterList[index], index, column);
}}
style={{ width: "45%" }}
/>
</FormGroup>
</div>
)
}
}
}
];
const data = [
{ city: "Yonkers", temp: 3 },
{ city: "Hartford", temp: 11 },
{ city: "Tampa", temp: 25 },
{ city: "Dallas", temp: 30 }
];
const options = {
filterType: "checkbox"
};
return (
<div className="App">
<MUIDataTable
title={"Employee List"}
data={data}
columns={columns}
options={options}
/>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
在选项中添加下面的代码。
options={{
sort: true,
sortOrder: { name: 'id', direction: 'desc' },
}}