我正在使用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>
答案 0 :(得分:4)
您可以使用具有predicate功能的过滤器来实现此目的。
function(value,index):谓词函数可用于写入任意过滤器。为数组的每个元素调用该函数。最终结果是谓词返回true的那些元素的数组。
$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;
}
找到匹配项后,您将collapsed
值设置为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>
答案 1 :(得分:0)
考虑完全抛弃angular-treeRepeat
模块并使用递归模板。本福斯特解释了它在blog post中是如何工作的,我认为它是一个更优雅(也不那么疯狂)的解决方案。
使用过滤器的工作示例: JSFiddle
HTML:
<div ng-app="app" ng-controller='AppCtrl'>
Filter: <input ng-model="myFilter" type="text">
<script type="text/ng-template" id="categoryTree">
{{ category.title }}
<ul ng-show="category.categories">
<li
ng-repeat="category in category.categories | filter:myFilter"
ng-include="'categoryTree'">
</li>
</ul>
</script>
<ul>
<li
ng-repeat="category in categories | filter:myFilter"
ng-include="'categoryTree'">
</li>
</ul>
</div>
JavaScript的:
var app = angular.module('app', [])
.controller('AppCtrl', function($scope) {
$scope.categories = [{
title: 'Computers',
categories: [{
title: 'Laptops',
categories: [{
title: 'Ultrabooks'
},{
title: 'Macbooks'
}]
},{
title: 'Desktops'
},{
title: 'Tablets',
categories: [{
title: 'Apple'
},{
title: 'Android'
}]
}
]
},{
title: 'Printers'
}];
});