数组树上的JS过滤器

问题描述 投票:0回答:1

我想过滤我的数组树并仅显示基于标签创建的节点

这是我的代码的输出: 在此输入图片描述

我添加了一个输入搜索,当我输入时我会更新我的状态,但我不知道如何更新我的树以仅显示过滤后的项目。 我正在使用 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

扁平数据,但不知道如何使其适应我的示例

javascript arrays tree treeview
1个回答
0
投票
  • 您可以在源上执行
    filter
    。就像下面这样。
  const filter = (e: any) => {
    setText(e.target.value);
    const result = MUI_X_PRODUCTS.filter((d) => {
      return d.label.includes(text);
    });
    setData(result);
  };
© www.soinside.com 2019 - 2024. All rights reserved.