Rendering a tree

2,774 views
Skip to first unread message

Nick R

unread,
Aug 21, 2011, 8:01:53 PM8/21/11
to angular
I ran into some trouble when I wanted to render a tree-like data
structure with angular.

Assuming you have a function get_children(node) that returns a list of
children for the given node, here's a naive approach:

<span ng:eval="parent = root">
<ng:include src="tree_node.html"></ng:include>

// tree_nodes.html:
<ul><li ng:repeat="node in get_children(parent)">
{{node.name}} is a child of {{parent.name}}
<span ng:eval="parent = node">
<ng:include src="tree_nodes.html"></ng:include>
</li></ul>

Unfortunately, this causes Chrome to crash the page, probably because
angular can't handle me changing the definition of parent inside the
child scope there. What is the correct way to do this?

Vojta Jina

unread,
Aug 22, 2011, 4:20:36 AM8/22/11
to ang...@googlegroups.com
Hi Nick,

you need a recursion in the template to do so. There is currently no widget for that...
Using ng:include for that sounds like a big overhead...

You can write a widget for that - similar to ng:repeat, but supporting recursion.

How deep is your structure ? If it's fixed you my try do it static, something like this: http://jsfiddle.net/vojtajina/u75us/1/

V.

Igor Minar

unread,
Aug 22, 2011, 11:42:55 AM8/22/11
to ang...@googlegroups.com
Does anyone on the mailing list feel like hacking up a prototype of a recursive repeater?

I think the api could look something like this:

<ul ngx:recurse="{tree: 'node in tree',
                  isLeaf: isLeafFn"}>
  <li ngx:recurse-leaf>Leaf: {{node.foo}}</li>
  <li ngx:recurse-non-leaf>Inner node: {{node.bar}}</li>
</ul> 

But there might be a better design...

I think that we do need to support this feature out of the box, but we need to experiment with the api and the implementation a bit before we do so..

/i

--
You received this message because you are subscribed to the Google Groups "angular" group.
To view this discussion on the web visit https://groups.google.com/d/msg/angular/-/QaLlFCDCDkIJ.

To post to this group, send email to ang...@googlegroups.com.
To unsubscribe from this group, send email to angular+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/angular?hl=en.

Mårten Dolk

unread,
Aug 22, 2011, 12:50:15 PM8/22/11
to ang...@googlegroups.com
+1

I think it would be useful to know the current depth as well,
scope.$depth maybe?

/mårten

2011/8/22 Igor Minar <iim...@gmail.com>:

Misko Hevery

unread,
Aug 22, 2011, 1:46:52 PM8/22/11
to ang...@googlegroups.com
ng:include is a bit heavy weight, but it does work just fine. Here is a demo: http://jsfiddle.net/mhevery/u75us/2/

-- Misko

Nick R

unread,
Aug 23, 2011, 3:35:00 AM8/23/11
to angular
I figured out how to do it, by tying the knot. ng:repeat creates a
new scope, so I need to eval the parent in that scope, but once I
enter that scope my reference to what would be parent is clobbered by
the current node. I have to create a second variable to carry it
through for one step. Behold:

// Root snippet in template
<ul><li ng:repeat="node in get_children(parent)">
<span ng:eval="parent = root">
<ng:include src="tree_nodes.html"></ng:include>
</li></ul>

// tree_node.html:
{{node.name}} is a child of {{parent.name}}
<span ng:eval="outer_node = node">
<ul><li ng:repeat="node in get_children(parent)">
<span ng:eval="parent = outer_node">
<ng:include src="tree_node.html"></ng:include>
</li></ul>

Misko Hevery

unread,
Aug 23, 2011, 10:43:01 AM8/23/11
to ang...@googlegroups.com
ng:eval, will soon go away. Any reason why my solution without ng:eval is not what you are looking for?


--

Nick R

unread,
Aug 23, 2011, 7:30:29 PM8/23/11
to angular
I tried to look at your solution last night but jsfiddle was throwing
http 500 errors loading the page.

Anyway, I wanted a way to reference the parent element. In my
application, each node shows up with a button that allows you to
dissociate it with its parent in this tree view. Without knowing the
relevant parent, the button wouldn't know what to dissociate it with.
My nodes area actually indexed in an interesting way where they don't
have a single parent -- in fact, they can have many parents, and the
tree looks different when you render it upside-down. Sorry for the
complexity, but suffice it to say, I need a reference to the parent
node!

(If you care about the reason it's complex: I'm modeling tasks that
have prerequisites. When you view a task, it generates two trees: a
tree of tasks and their prerequisites you'll have to finish before
this task will be doable, and a tree of all the things you'll be able
to do once you complete this task and other tasks it is a prerequisite
for, etc. It's an experimental todo app. I originally implemented it
with google gears for the embedded sqlite implementation and full text
search, but it was much easier to re-make in angular!)

I hope ng:eval doesn't go away! Eval-ing into repeats works pretty
nicely. Eval-ing into includes would be better though. And real
recursion support with automatic $parent references (like in knockout)
would be awesome.

ngit...@sightlineinnovation.com

unread,
Jun 19, 2012, 3:19:47 PM6/19/12
to ang...@googlegroups.com
After some searching: https://groups.google.com/forum/?fromgroups#!topic/angular/TbpjE-5XEM0

Works on the newest AngularJS quite well.

Vojta Jína

unread,
Jun 30, 2012, 2:03:33 AM6/30/12
to ang...@googlegroups.com
Nice.

On Tue, Jun 19, 2012 at 12:19 PM, <ngit...@sightlineinnovation.com> wrote:
After some searching: https://groups.google.com/forum/?fromgroups#!topic/angular/TbpjE-5XEM0

Works on the newest AngularJS quite well.

--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To view this discussion on the web visit https://groups.google.com/d/msg/angular/-/UBAGxSRBicYJ.
Reply all
Reply to author
Forward
0 new messages