I want to filter on my array tree and display only founded node based on the label
this is my output with my code : enter image description here
I've added a input search and when I type into I update my state but I don't know how to update my tree to display only filtered items.. I'm using Material UI and there is no filter option on documentation I've tried flat data but don'k know how to adapt it on my example.. this is my code :
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>
);
}
the demo link is here : DEMO
flat data but don(t know how to adapt it to my example
filter
on source. Just like below.label
, you can play with it fi you want to dive deep. const filter = (e: any) => {
setText(e.target.value);
const result = MUI_X_PRODUCTS.filter((d) => {
return d.label.includes(text); // condition as per your requirement
});
setData(result);
};
text
is available inside children
or not you can do something like below,return d.label.includes(text) || d.children.some(child => child.label.includes(text))