我试图在递归树中有我的节点的唯一标题.
因此,当我给我的节点赋予标题时,它应检查该标题是否已被其他节点使用.如果采用它,它应该警告用户,它应该将该节点值重置为先前的值.
没有两个节点应该具有相同的标题.
但是这里结构是递归的,所以我不知道如何做到这一点.
注意:我想在文本框失去焦点时立即执行此操作.
var app = angular.module("myApp",[]); app.controller("TreeController",function ($scope) { $scope.delete = function (data) { data.nodes = []; }; $scope.add = function (data) { var post = data.nodes.length + 1; var newName = data.name + '-' + post; data.nodes.push({ name: newName,nodes: [],selected : false,myObj: { name: newName} }); }; $scope.tree = [{ name: "Node",selected: false }]; $scope.setActive = function ($event,data) { $event.stopPropagation(); $scope.selectedData = data; clearDivSelection($scope.tree); data.selected = true; }; function clearDivSelection(items) { items.forEach(function (item) { item.selected = false; if (item.nodes) { clearDivSelection(item.nodes); } }); } $scope.checkDuplicateNodeName = function () { alert() } });
ul { list-style: circle; } li { margin-left: 20px; } .active { background-color: #ccffcc;}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <ul ng-app="myApp" ng-controller="TreeController"> <li ng-repeat="data in tree" ng-include="'tree_item_renderer.html'"></li> <script type="text/ng-template" id="tree_item_renderer.html"> <div ng-class="{'active': data.selected}" > {{data.myObj.name}}</div> <button ng-click="add(data)">Add node</button> <button ng-click="delete(data)" ng-show="data.nodes.length > 0">Delete nodes</button> <ul> <li ng-repeat="data in data.nodes" ng-include="'tree_item_renderer.html'" ng-click="setActive($event,data)"></li> </ul> </script> <div style="margin-left:100px;"> Title : <input type="text" ng-model="selectedData.myObj.name" ng-blur="checkDuplicateNodeName()" /> Location : <input type="text" ng-model="selectedData.myObj.location" /> </div> </ul>
解决方法
我的解决方案
>在blur上存储经过验证的名称副本(意思是有3个名字,但我不知道myObj.name的点,所以我按原样保留,你可以清理)
>递归找到dupes,先停下来为true.如果有欺骗,请使用最后一个有效名称,否则更新最后一个有效名称.
个为什么
>您只想在模糊时验证名称. angular提供了通过解析器和格式化程序在每次更改时验证ng-model的方法,这将完全限制用户保持欺骗名称.有很多方法可以解决这个问题(验证器,编辑而不会持久),并且都需要不同类型的解决方案.探索并选择最适合您的方法
>使用hashMap(我的第一个想法)将需要重命名和删除的清理逻辑,这将最终使代码进一步复杂化
如果只希望在节点树中搜索dupes,则需要存储对父节点的引用,并使用getTree方法确定要搜索的根节点.
var app = angular.module("myApp",[]); app.controller("TreeController",function($scope) { $scope.delete = deleteNodes; $scope.add = add; $scope.setActive = setActive; $scope.checkDuplicateNodeName = checkDuplicateNodeName; $scope.trees = [{ name: "Node",selected: false },{ name: "Node2",selected: false }]; function deleteNodes(data) { data.nodes = []; } function add(data) { var post = data.nodes.length + 1; var newName = data.name + '-' + post; data.nodes.push({ name: newName,selected: false,validatedName: newName }); } function setActive($event,data) { $event.stopPropagation(); if($scope.selectedData) { $scope.selectedData.selected = false; } $scope.selectedData = data; data.selected = true; } function checkDuplicateNodeName() { if(!$scope.selectedData) return; var dupe = false; for(var idx = 0; idx < $scope.trees.length; idx++) { if(isDuplicateName($scope.trees[idx],$scope.selectedData)) { dupe = true; break; } } if(dupe){ alert('The name "' + $scope.selectedData.name + '" already exists'); $scope.selectedData.name = $scope.selectedData.validatedName; } else { $scope.selectedData.validatedName = $scope.selectedData.name; } } function getTree(node){ while(node.parent) { node = node.parent; } return node; } function isDuplicateName(node,nodetocheck) { var dupeName = node != nodetocheck && node.name && nodetocheck.name && node.name == nodetocheck.name; if(dupeName) return true; if(node.nodes){ for(var idx=0; idx< node.nodes.length; idx++) { if(isDuplicateName(node.nodes[idx],nodetocheck)){ return true; } } } return false; } });
ul { list-style: circle; } li { margin-left: 20px; } .active { background-color: #ccffcc; }
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <ul ng-app="myApp" ng-controller="TreeController"> <li ng-repeat="data in trees" ng-include="'tree_item_renderer.html'"></li> <script type="text/ng-template" id="tree_item_renderer.html"> <div ng-class="{'active': data.selected}"> {{data.name}}</div> <button ng-click="add(data)">Add node</button> <button ng-click="delete(data)" ng-show="data.nodes.length > 0">Delete nodes</button> <ul> <li ng-repeat="data in data.nodes" ng-include="'tree_item_renderer.html'" ng-click="setActive($event,data)"></li> </ul> </script> <div style="margin-left:100px;"> Title : <input type="text" ng-model="selectedData.name" ng-blur="checkDuplicateNodeName()" /> Location : <input type="text" ng-model="selectedData.myObj.location" /> </div> </ul>