javascript – AngularJS过滤器不扩展过滤节点

我正在使用https://github.com/tchatel/angular-treeRepeat,并尝试过滤未扩展的节点.所以我修改了这个代码以包含AngularJS过滤器:

treeRepeat.html:

<p id="expand-collapse-all">
    <a href="" ng-click="expandAll()">Expand all</a>
    <a href="" ng-click="collapseAll()">Collapse all</a>
</p>


Filter : <input ng-model="myFilter" type="text">

<ul frang-tree>
  <li frang-tree-repeat="node in treeData | filter:myFilter">
      <div><span class="icon"
                 ng-class="{collapsed: node.collapsed, expanded: !node.collapsed}"
                 ng-show="node.children && node.children.length > 0"
                 ng-click="node.collapsed = !node.collapsed"></span>
           <span class="label"
                 ng-class="{folder: node.children && node.children.length > 0}"
                 ng-bind="node.label"
                 ng-click="action(node)"></span>
      </div>
      <ul ng-if="!node.collapsed && node.children && node.children.length > 0"
          frang-tree-insert-children="node.children  | filter:myFilter"></ul>
  </li>
</ul>

如果所有树节点都已展开,则可按预期方式工作:
controllers.js上的第20行:

$scope.treeData = JSON.parse("[ { \"label\": \"root\", \"children\": [ { \"label\": \"folder A\", \"collapsed\": true, \"children\": [ { \"label\": \"folder B\", \"collapsed\": true, \"children\": [ { \"label\": \"file B1\", \"collapsed\": true }, { \"label\": \"file B2\", \"collapsed\": true } ] }, { \"label\": \"file A1\", \"collapsed\": true }, { \"label\": \"file A2\", \"collapsed\": true }, { \"label\": \"file A3\", \"collapsed\": true }, { \"label\": \"file A4\", \"collapsed\": true } ] }, { \"label\": \"folder C\", \"collapsed\": true, \"children\": [ { \"label\": \"folder D\", \"collapsed\": true, \"children\": [ { \"label\": \"folder E\", \"collapsed\": true, \"children\": [ { \"label\": \"file E1\", \"collapsed\": true }, { \"label\": \"file E2\", \"collapsed\": true }, { \"label\": \"file E3\", \"collapsed\": true } ] } ] }, { \"label\": \"folder F\", \"collapsed\": true, \"children\": [ { \"label\": \"file F1\", \"collapsed\": true }, { \"label\": \"file F2\", \"collapsed\": true } ] }, { \"label\": \"file C1\", \"collapsed\": true } ] }, { \"label\": \"folder G\", \"collapsed\": true, \"children\": [ { \"label\": \"file G1\", \"collapsed\": true }, { \"label\": \"file G2\", \"collapsed\": true }, { \"label\": \"file G3\", \"collapsed\": true }, { \"label\": \"file G4\", \"collapsed\": true } ] }, { \"label\": \"folder H\", \"collapsed\": true, \"children\": [ { \"label\": \"file H1\", \"collapsed\": true }, { \"label\": \"file H2\", \"collapsed\": true }, { \"label\": \"file H3\", \"collapsed\": true } ] } ] } ]");

但是如果节点被折叠,则匹配的节点被扩展/可见.树仍然崩溃.折叠节点的配置:
controllers.js上的第21行:

$scope.treeData = JSON.parse("[ { \"label\": \"root\", \"children\": [ { \"label\": \"folder A\", \"collapsed\": true, \"children\": [ { \"label\": \"folder B\", \"collapsed\": true, \"children\": [ { \"label\": \"file B1\", \"collapsed\": true }, { \"label\": \"file B2\", \"collapsed\": true } ] }, { \"label\": \"file A1\", \"collapsed\": true }, { \"label\": \"file A2\", \"collapsed\": true }, { \"label\": \"file A3\", \"collapsed\": true }, { \"label\": \"file A4\", \"collapsed\": true } ] }, { \"label\": \"folder C\", \"collapsed\": true, \"children\": [ { \"label\": \"folder D\", \"collapsed\": true, \"children\": [ { \"label\": \"folder E\", \"collapsed\": true, \"children\": [ { \"label\": \"file E1\", \"collapsed\": true }, { \"label\": \"file E2\", \"collapsed\": true }, { \"label\": \"file E3\", \"collapsed\": true } ] } ] }, { \"label\": \"folder F\", \"collapsed\": true, \"children\": [ { \"label\": \"file F1\", \"collapsed\": true }, { \"label\": \"file F2\", \"collapsed\": true } ] }, { \"label\": \"file C1\", \"collapsed\": true } ] }, { \"label\": \"folder G\", \"collapsed\": true, \"children\": [ { \"label\": \"file G1\", \"collapsed\": true }, { \"label\": \"file G2\", \"collapsed\": true }, { \"label\": \"file G3\", \"collapsed\": true }, { \"label\": \"file G4\", \"collapsed\": true } ] }, { \"label\": \"folder H\", \"collapsed\": true, \"children\": [ { \"label\": \"file H1\", \"collapsed\": true }, { \"label\": \"file H2\", \"collapsed\": true }, { \"label\": \"file H3\", \"collapsed\": true } ] } ] } ]");

Plunkr:https://plnkr.co/edit/CtXlRfdreolTTc018c0A?p=preview

我需要手动扩展节点的用户类型,还是有一个角度配置,我可以用来扩展这些节点?

我尝试添加一个自定义功能,每次用户键入时触发:

  function matchChildNode(objData , parentNode) {

        angular.forEach(objData, function(childNode, key) {

                var searchText = "";
                //AngularJS does not initialise the searchText var until used. As the function is re-initialised for every node
                //need to check if is undefined
                if ($scope.searchText == undefined) {
                    searchText = ""
                } else {
                    searchText = $scope.searchText
                }

                if (searchText.toLowerCase() === childNode.label.toLowerCase()) {
                    parentNode.collapsed = false
                }       

                matchChildNode(childNode.children , childNode);

  });
  } 
}

但是,对于每个关键字用户类型遍历整个树结构,这是非常低效的.这也适用于完全匹配的文本:searchText.toLowerCase()=== childNode.label.toLowerCase().尝试使用contains而不是===没有成功.

plnkr src:

app.css (removed due to stackoverflow 30000 character limitation when asking questions) 

directives.js (removed due to stackoverflow 30000 character limitation when asking questions) 

filter.js : 

'use strict';

angular.module('app.filters', []);

index.html : 


<!doctype html>
<html lang="en" ng-app="app">
<head>
  <meta charset="utf-8">
  <title>treeRepeat demo</title>
  <link rel="stylesheet" href="app.css"/>
</head>

<body>

  <h1>treeRepeat</h1>
  <div id="menu" ng-controller="MenuCtrl">
      <ul>
          <li ng-repeat="item in menu" ng-class="{selected: item == getCurrentMenuItem()}"><a href="#/{{item.index}}">{{item.shortLabel}}</a></li>
      </ul>
      <h2>{{getCurrentMenuItem().fullLabel}}</h2>
  </div>

  <ng-view></ng-view>

  <script src="angular.js"></script>
  <script src="angular-route.js"></script>
  <script src="app.js"></script>
  <script src="services.js"></script>
  <script src="controllers.js"></script>
  <script src="filters.js"></script>
  <script src="directives.js"></script>
</body>
</html>

services.js : 

'use strict';

angular.module('app.services', [])
    .constant('menu', []);

treerepeat.html : 

<p id="expand-collapse-all">
    <a href="" ng-click="expandAll()">Expand all</a>
    <a href="" ng-click="collapseAll()">Collapse all</a>
</p>


Filter : <input ng-model="myFilter" type="text">

<ul frang-tree>
  <li frang-tree-repeat="node in treeData | filter:myFilter">
      <div><span class="icon"
                 ng-class="{collapsed: node.collapsed, expanded: !node.collapsed}"
                 ng-show="node.children && node.children.length > 0"
                 ng-click="node.collapsed = !node.collapsed"></span>
           <span class="label"
                 ng-class="{folder: node.children && node.children.length > 0}"
                 ng-bind="node.label"
                 ng-click="action(node)"></span>
      </div>
      <ul ng-if="!node.collapsed && node.children && node.children.length > 0"
          frang-tree-insert-children="node.children  | filter:myFilter"></ul>
  </li>
</ul>
您可以通过使用具有predicate功能的过滤器来实现此目的.

function(value, index): A predicate function can be used to write arbitrary filters. The function is called for each element of array. The final result is an array of those elements that the predicate returned true for.

>创建谓词函数

$scope.getFilter = function(value, index){
  if(!$scope.myFilter || $scope.myFilter === '' && (value.label === 'root')){
      $scope.collapseAll();
      return true;
  }
  if (findMatch(value, $scope.myFilter)){
      value.collapsed = false;
      return true;
    }else{
      value.collapsed = true;
      return false;
    }
}

>创建一个检查当前项目是否匹配的函数(该函数从谓词函数调用)

function findMatch(value, filter) {
    var found = false;
    if(value.label.toLowerCase().indexOf(filter) > -1){
        value.collapsed = false;
        found = true;
    }
    if(!value.children || value.children.length===0){
        if(value.collapsed!== undefined){
            value.collapsed = true;
            return found;
          } 
        }
        for (var i = 0; i < value.children.length; i++) {
            if (value.children[i].label.toLowerCase().indexOf(filter) > -1) {
                //match found
                value.collapsed = false;
                value.children[i].collapsed = false;
                found = true;
            } else {
                //check child items
                if(value.children[i].children && value.children[i].children.length>0)
                {
                  if (findMatchingChildren(value.children[i].children, filter)) {
                    value.children[i].collapsed = false;
                    found = true;
                  }else{
                    value.children[i].collapsed = true;
                  } 
                }
            }
        }

        return found;
}

3.创建一个循环遍历当前项目的子项目的函数,该函数在步骤2中调用该函数.最后使用一个递归函数来检查所有级别.

function findMatchingChildren(children, filter) {
    var found = false;
    for (var i = 0; i < children.length; i++) {
        if (findMatch(children[i], filter)) {
            children[i].collapsed = false;
            found = true;
        }else{
            children[i].collapsed = true;
        }
    }
    return found;
 } 

找到匹配的项目时,将折叠值设置为false

请参阅工作示例here

HTML

<p id="expand-collapse-all">
    <a href="" ng-click="expandAll()">Expand all</a>
    <a href="" ng-click="collapseAll()">Collapse all</a>
</p>
Filter : <input ng-model="myFilter" type="text">
<ul frang-tree>
    <li frang-tree-repeat="node in treeData | filter:getFilter">
        <div>
            <span class="icon"
                ng-class="{collapsed: node.collapsed, expanded: !node.collapsed}"
                ng-show="node.children && node.children.length > 0"
                ng-click="node.collapsed = !node.collapsed"></span>
            <span class="label"
                ng-class="{folder: node.children && node.children.length > 0}"
                ng-bind="node.label"
                ng-click="action(node)"></span>
        </div>
        <ul ng-if="!node.collapsed && node.children && node.children.length>0" frang-tree-insert-children="node.children  | filter:myFilter"></ul>
 </li>
</ul>
http://stackoverflow.com/questions/34595019/angularjs-filter-not-expanding-filtered-nodes

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:javascript – AngularJS过滤器不扩展过滤节点