我想过滤我的数组树并仅显示基于标签创建的节点
这是我的代码的输出: 在此输入图片描述
我添加了一个输入搜索,当我输入时我会更新我的状态,但我不知道如何更新我的树以仅显示过滤后的项目。 我正在使用 Material UI,文档中没有过滤器选项 我尝试过平面数据,但不知道如何在我的示例中调整它。 这是我的代码:
import * as React from 'react';
import Box from '@mui/material/Box';
import { RichTreeView } from '@mui/x-tree-view/RichTreeView';
import { TreeViewBaseItem } from '@mui/x-tree-view/models';
const MUI_X_PRODUCTS: TreeViewBaseItem[] = [
{
id: 'grid',
label: 'Data Grid',
children: [
{ id: 'grid-community', label: '@mui/x-data-grid' },
{ id: 'grid-pro', label: '@mui/x-data-grid-pro' },
{ id: 'grid-premium', label: '@mui/x-data-grid-premium' },
],
},
{
id: 'pickers',
label: 'Date and Time Pickers',
children: [
{ id: 'pickers-community', label: '@mui/x-date-pickers' },
{ id: 'pickers-pro', label: '@mui/x-date-pickers-pro' },
],
},
{
id: 'charts',
label: 'Charts',
children: [{ id: 'charts-community', label: '@mui/x-charts' }],
},
{
id: 'tree-view',
label: 'Tree View',
children: [{ id: 'tree-view-community', label: '@mui/x-tree-view' }],
},
{
id: '1',
label: 'test',
children: [
{ id: '11', label: 'AAAA' },
{ id: '12', label: 'BBBB' },
],
},
];
function getParentIds(items: TreeViewBaseItem[], id: string) {
const parentIds: string[] = [];
for (const item of items) {
if (item.children) {
if (item.children.some((child) => child.id === id)) {
// The current item is a parent of the supplied id
parentIds.push(item.id);
// Recursively call the function for the parent item
const grandParentIds = getParentIds(items, item.id);
parentIds.push(...grandParentIds);
} else {
// Recursively call the function for the children of the current item
const childParentIds = getParentIds(item.children, id);
parentIds.push(...childParentIds);
}
}
}
return parentIds;
}
function getParentNode(
items: TreeViewBaseItem[],
id: string
): TreeViewBaseItem | undefined {
for (const item of items) {
if (item.children) {
if (item.children.some((child) => child.id === id)) {
// The current item is the parent of the supplied id
return item;
} else {
// Recursively call the function for the children of the current item
const parentNode = getParentNode(item.children, id);
if (parentNode) {
return parentNode;
}
}
}
}
// No parent found
return undefined;
}
function getSelectedIdsAndChildrenIds(
items: TreeViewBaseItem[],
selectedIds: string[]
) {
const selectedIdIncludingChildrenIds = new Set([...selectedIds]);
for (const item of items) {
if (selectedIds.includes(item.id)) {
// Add the current item's id to the result array
selectedIdIncludingChildrenIds.add(item.id);
// Recursively call the function for the children of the current item
if (item.children) {
const childrenIds = item.children.map((child) => child.id);
const childrenSelectedIds = getSelectedIdsAndChildrenIds(
item.children,
childrenIds
);
childrenSelectedIds.forEach((selectedId) =>
selectedIdIncludingChildrenIds.add(selectedId)
);
}
} else if (item.children) {
// walk the children to see if selections lay in there also
const childrenSelectedIds = getSelectedIdsAndChildrenIds(
item.children,
selectedIds
);
childrenSelectedIds.forEach((selectedId) =>
selectedIdIncludingChildrenIds.add(selectedId)
);
}
}
return [...Array.from(selectedIdIncludingChildrenIds)];
}
function determineIdsToSet(
items: TreeViewBaseItem[],
newIds: string[],
currentIds: string[]
) {
const isDeselectingNode = currentIds.length > newIds.length;
if (isDeselectingNode) {
const removed = currentIds.filter((id) => !newIds.includes(id))[0];
const parentIdsToRemove = getParentIds(items, removed);
const childIdsToRemove = getSelectedIdsAndChildrenIds(items, [removed]);
const newIdsWithParentsAndChildrenRemoved = newIds.filter(
(id) => !parentIdsToRemove.includes(id) && !childIdsToRemove.includes(id)
);
return newIdsWithParentsAndChildrenRemoved;
}
const added = newIds.filter((id) => !currentIds.includes(id))[0];
const parent = getParentNode(items, added);
if (parent) {
const childIds = parent.children?.map((node) => node.id) ?? [];
const allChildrenSelected = childIds.every((id) => newIds.includes(id));
if (allChildrenSelected) {
return [...getSelectedIdsAndChildrenIds(items, newIds), parent.id];
}
}
return getSelectedIdsAndChildrenIds(items, newIds);
}
export default function CheckboxSelection() {
const [selectedIds, setSelectedIds] = React.useState<string[]>([]);
const [data, setData] = React.useState(MUI_X_PRODUCTS);
const [filterok, setFilterok] = React.useState<string[]>([]);
const [text, setText] = React.useState<string>('');
function myFlat(a: any, prefix = '') {
return a.reduce(function (flattened: any, { id, label, children }) {
id = prefix + id;
return flattened
.concat([{ id, label }])
.concat(children ? myFlat(children, id) : []);
}, []);
}
React.useEffect(() => {
if (selectedIds.length > 0) {
console.log(selectedIds);
}
}, [selectedIds]);
React.useEffect(() => {
if (text !== '') {
console.log(text);
}
}, [text]);
const filter = (e: any) => {
setText(e.target.value);
};
const handleSelectedItemsChange = (
_event: React.SyntheticEvent,
ids: string[]
) => {
setSelectedIds(determineIdsToSet(MUI_X_PRODUCTS, ids, selectedIds));
};
return (
<Box sx={{ height: 264, flexGrow: 1, maxWidth: 400 }}>
<input type="text" onChange={filter} value={text} />
<RichTreeView
multiSelect={true}
checkboxSelection={true}
selectedItems={selectedIds}
onSelectedItemsChange={handleSelectedItemsChange}
items={data}
/>
</Box>
);
}
演示链接在这里:DEMO
扁平数据,但不知道如何使其适应我的示例
filter
。就像下面这样。 const filter = (e: any) => {
setText(e.target.value);
const result = MUI_X_PRODUCTS.filter((d) => {
return d.label.includes(text);
});
setData(result);
};