I'm trying to create a breadcrumb without using the url (the route provider) and without using jQuery. I have a tree like that
Humans
Trees
Animals
Cats
Lions
Dogs
Terrier
Bulldog
Cocker
Cars
and I'd like when I click on Cocker to display
Animals / Dogs / Cocker
So, I created a recursive function in order to find parent/parents for each element that I click on but it doesn't work correctly. It finds that an element has a parent, it also finds the first parent of an element but it doesn't show the second parent. For instance instead of
Animals / Dogs / Cocker
it shows
Dogs / Cocker
That's my function
var count = 0;
function iterate(obj) {
for(var key in obj) {
var elem = obj[key];
if(key === "children") {
count++;
}
if(typeof elem === "object") {
if(elem.children === undefined){
elem.children = 1;
}
if(elem.children.length !==1){
iterate(elem);
$scope.showTrail = elem.children;
$scope.elem = elem;
}
}
}
if($scope.elem === undefined){
$scope.elem = {};
$scope.elem.children = {};
$scope.elem.roleName = {};
}
for (var i = 0; i<$scope.elem.children.length; i++) {
if($scope.elem.children[i].roleName === selNode.roleName) {
console.log($scope.elem.roleName + " is a parent of " + selNode.roleName);
}
}
}
iterate($scope.treeData);
and that's the JSON
[
{ "roleName" : "Humans", "roleId" : "role2", "children" : [
{ "roleName" : "", "roleId" : "role11", "children" : [] }
]},
{ "roleName" : "Trees", "roleId" : "role2", "children" : [
{ "roleName" : "", "roleId" : "role11", "children" : [] }
]},
{ "roleName" : "Animals", "roleId" : "role2", "children" : [
{ "roleName" : "Cats", "roleId" : "role11", "children" : [
{ "roleName" : "", "roleId" : "role11", "children" : [] }
]},
{ "roleName" : "Lions", "roleId" : "role11", "children" : [
{ "roleName" : "", "roleId" : "role11", "children" : [] }
]},
{ "roleName" : "Dogs", "roleId" : "role11", "children" : [
{ "roleName" : "Terrier", "roleId" : "role11", "children" : [
{ "roleName" : "", "roleId" : "role11", "children" : [] }
]},
{ "roleName" : "Bulldog", "roleId" : "role11", "children" : [
{ "roleName" : "", "roleId" : "role11", "children" : [] }
]},
{ "roleName" : "Cocker", "roleId" : "role11", "children" : [
{ "roleName" : "", "roleId" : "role11", "children" : [] }
]},
]}
]},
{ "roleName" : "Cars", "roleId" : "role2", "children" : [
{ "roleName" : "", "roleId" : "role11", "children" : [] }
]}
]
Any help please, any idea. Thank you very much.
I'm trying to create a breadcrumb without using the url (the route provider) and without using jQuery. I have a tree like that
Humans
Trees
Animals
Cats
Lions
Dogs
Terrier
Bulldog
Cocker
Cars
and I'd like when I click on Cocker to display
Animals / Dogs / Cocker
So, I created a recursive function in order to find parent/parents for each element that I click on but it doesn't work correctly. It finds that an element has a parent, it also finds the first parent of an element but it doesn't show the second parent. For instance instead of
Animals / Dogs / Cocker
it shows
Dogs / Cocker
That's my function
var count = 0;
function iterate(obj) {
for(var key in obj) {
var elem = obj[key];
if(key === "children") {
count++;
}
if(typeof elem === "object") {
if(elem.children === undefined){
elem.children = 1;
}
if(elem.children.length !==1){
iterate(elem);
$scope.showTrail = elem.children;
$scope.elem = elem;
}
}
}
if($scope.elem === undefined){
$scope.elem = {};
$scope.elem.children = {};
$scope.elem.roleName = {};
}
for (var i = 0; i<$scope.elem.children.length; i++) {
if($scope.elem.children[i].roleName === selNode.roleName) {
console.log($scope.elem.roleName + " is a parent of " + selNode.roleName);
}
}
}
iterate($scope.treeData);
and that's the JSON
[
{ "roleName" : "Humans", "roleId" : "role2", "children" : [
{ "roleName" : "", "roleId" : "role11", "children" : [] }
]},
{ "roleName" : "Trees", "roleId" : "role2", "children" : [
{ "roleName" : "", "roleId" : "role11", "children" : [] }
]},
{ "roleName" : "Animals", "roleId" : "role2", "children" : [
{ "roleName" : "Cats", "roleId" : "role11", "children" : [
{ "roleName" : "", "roleId" : "role11", "children" : [] }
]},
{ "roleName" : "Lions", "roleId" : "role11", "children" : [
{ "roleName" : "", "roleId" : "role11", "children" : [] }
]},
{ "roleName" : "Dogs", "roleId" : "role11", "children" : [
{ "roleName" : "Terrier", "roleId" : "role11", "children" : [
{ "roleName" : "", "roleId" : "role11", "children" : [] }
]},
{ "roleName" : "Bulldog", "roleId" : "role11", "children" : [
{ "roleName" : "", "roleId" : "role11", "children" : [] }
]},
{ "roleName" : "Cocker", "roleId" : "role11", "children" : [
{ "roleName" : "", "roleId" : "role11", "children" : [] }
]},
]}
]},
{ "roleName" : "Cars", "roleId" : "role2", "children" : [
{ "roleName" : "", "roleId" : "role11", "children" : [] }
]}
]
Any help please, any idea. Thank you very much.
Share Improve this question edited Nov 24, 2013 at 13:44 jimakos17 asked Nov 18, 2013 at 16:35 jimakos17jimakos17 9354 gold badges15 silver badges34 bronze badges 3- Could you provide the real data structure (nested objects/arrays)? – user1636522 Commented Nov 18, 2013 at 16:47
- create demo in plunker with directive that generates tree. SHould be able to create breadcrumb as attribute while directive gets piled – charlietfl Commented Nov 18, 2013 at 18:12
- I updated the question by adding a recursive function which finds a parent element but not all the parents of each element. Any help please!!! – jimakos17 Commented Nov 19, 2013 at 12:09
3 Answers
Reset to default 4 +50You are iterating over the tree, but it won't help if you don't keep some information. The simplest solution to your problem is to build an index of all nodes that points to their parents.
This code will work if roleName
has unique values across the whole tree:
var tree = [
{ "roleName" : "Humans", "roleId" : "role2", "children" : []},
{ "roleName" : "Trees", "roleId" : "role2", "children" : []},
{ "roleName" : "Animals", "roleId" : "role2", "children" : [
{ "roleName" : "Cats", "roleId" : "role11", "children" : []},
{ "roleName" : "Lions", "roleId" : "role11", "children" : []},
{ "roleName" : "Dogs", "roleId" : "role11", "children" : [
{ "roleName" : "Terrier", "roleId" : "role11", "children" : []},
{ "roleName" : "Bulldog", "roleId" : "role11", "children" : []},
{ "roleName" : "Cocker", "roleId" : "role11", "children" : []},
]}
]},
{ "roleName" : "Cars", "roleId" : "role2", "children" : []}
];
var index = {};
function buildIndex(root, children) {
for(var i in children) {
index[children[i].roleName] = root;
buildIndex(children[i].roleName, children[i].children);
}
}
buildIndex("Root", tree);
function getPath(leaf) {
return index[leaf] ? getPath(index[leaf]).concat([leaf]) : [leaf];
}
getPath("Bulldog");// returns ["Root", "Animals", "Dogs", "Bulldog"]
JSFiddle: http://jsfiddle/E49Ey/
However it has nothing to do with Angular, except the data resides in the scope. If you have a DOM tree built from this data, then you could get the breadcrumb right from the DOM by going up the tree.
Hey I put together a quick plunkr doing what your looking for... except it doesn't reverse-traverse up the data tree.
http://embed.plnkr.co/wAJYiAjy58vUEsg4Kr2C
If your looking to actually looking to run up the data tree let me know and I'll modify the plunkr
You can of course solve it with a recursive function similar to what you showed in the question. What about a solution like this:
function getPath(obj, selNode, pathSoFar) {
if (obj.roleName == selNode.roleName) {
return pathSoFar + '\\' + obj.roleName;
}
else if (obj.children) {
for (var i=0 ; i<obj.children.length ; i++) {
var temp = getPath(obj.children[i], selNode,
pathSoFar + '\\' + obj.roleName);
if (temp != null) {
return temp;
}
}
}
return null;
}
getPath(rootObj, selNode, '');
I hope it helps and explains the solution idea.