【问题标题】:How to effectively filter tree view retaining its existing structure?如何有效过滤保留其现有结构的树视图?
【发布时间】:2017-12-30 14:04:23
【问题描述】:

我有一个树形结构的 JSON,它应该被过滤并且结果应该保留树形结构。

var tree = [
  {
    text: "Parent 1",
    nodes: [
      {
        text: "Child 1",
        type: "Child",
        nodes: [
          {
            text: "Grandchild 1"
            type: "Grandchild"
          },
          {
            text: "Grandchild 2"
            type: "Grandchild"
          }
        ]
      },
      {
        text: "Child 2",
        type: "Child"
      }
    ]
  },
  {
    text: "Parent 2",
    type: "Parent"
  },
  {
    text: "Parent 3",
    type: "Parent"
  }
];

例子:

1)如果搜索查询是 Parent 1

预期结果:

[
  {
    text: "Parent 1",
    nodes: [
      {
        text: "Child 1",
        type: "Child",
        nodes: [
          {
            text: "Grandchild 1"
            type: "Grandchild"
          },
          {
            text: "Grandchild 2"
            type: "Grandchild"
          }
        ]
      },
      {
        text: "Child 2",
        type: "Child"
      }
    ]
  }
]

2)如果搜索查询是 Child 1

预期结果:

[
  {
    text: "Parent 1",
    nodes: [
      {
        text: "Child 1",
        type: "Child",
        nodes: [
          {
            text: "Grandchild 1"
            type: "Grandchild"
          },
          {
            text: "Grandchild 2"
            type: "Grandchild"
          }
        ]
      }
    ]
  }
]

3)如果搜索查询是孙子 2

预期结果:

[
  {
    text: "Parent 1",
    nodes: [
      {
        text: "Child 1",
        type: "Child",
        nodes: [
          {
            text: "Grandchild 2"
            type: "Grandchild"
          }
        ]
      }
    ]
  }
]

我需要保留基于节点级别的树结构(此处为类型)。到目前为止,我已经尝试递归过滤,但无法重新映射结果。

angular.module("myApp",[])
   .filter("filterTree",function(){
       return function(items,id){
          var filtered = [];
          var recursiveFilter = function(items,id){
              angular.forEach(items,function(item){
                 if(item.text.toLowerCase().indexOf(id)!=-1){
                    filtered.push(item);
                 }
                 if(angular.isArray(item.items) && item.items.length > 0){
                    recursiveFilter(item.items,id);              
                 }
              });
          };
          recursiveFilter(items,id);
          return filtered;
       }; 
    });
});

我的 JSON 非常大,因此基于类型的重新映射预计将在过滤器本身中完成。 请指教。

【问题讨论】:

    标签: javascript angularjs optimization tree treeview


    【解决方案1】:

    您可以使用嵌套递归方法并过滤树,同时尊重找到的项目。

    此解决方案不会改变原始数据。

    function filter(array, text) {
        const getNodes = (result, object) => {
            if (object.text === text) {
                result.push(object);
                return result;
            }
            if (Array.isArray(object.nodes)) {
                const nodes = object.nodes.reduce(getNodes, []);
                if (nodes.length) result.push({ ...object, nodes });
            }
            return result;
        };
    
        return array.reduce(getNodes, []);
    }
    
    var tree = [{ text: "Parent 1", nodes: [{ text: "Child 1", type: "Child", nodes: [{ text: "Grandchild 1", type: "Grandchild" }, { text: "Grandchild 2", type: "Grandchild" }] }, { text: "Child 2", type: "Child" }] }, { text: "Parent 2", type: "Parent" }, { text: "Parent 3", type: "Parent" }];
    
    console.log(filter(tree, 'Parent 1'));
    console.log(filter(tree, 'Child 1'));
    console.log(filter(tree, 'Grandchild 2'));
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

    • 谢谢!这个答案救了我。
    • 非常好,花了我三个小时才读到突变的副作用...非常感谢。
    • 很好的解决方案!
    • 如果我必须在示例 1 的情况下显示空节点怎么办,因为没有孩子有文本“父母 1”??
    • @user3106347,请提出一个新问题。
    猜你喜欢
    • 1970-01-01
    • 2010-11-17
    • 2022-01-07
    • 2010-11-21
    • 2015-06-29
    • 2013-12-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多