On a couple of my projects, I’ve wanted a dynamic tree representation of a group of objects. acts_as_nested_set and it variants (such as awesome_nested_set) work well for creating the back-end structure. There are plenty of JavaScript libraries that will help you create a dynamic tree. I’ve used YUI 2 TreeView in the past, and this time I wanted to use Dynatree.
What I find takes time is pulling the two together. Specifically, I like to output the items in an unordered list and then used the JavaScript library to rebuild the list as a dynamic tree. That way the list degrades nicely if there is a JavaScript issue. However, getting an acts_as_nested_set group into an nested ordered list is tiresome.
So to prevent me having to reinvent the conversion of a nested set into a nested unordered list, I’ve created TreeDecorator. It is installed into a rails app with:
With that in place I could create this helper method (My nested set object is Event):
hanger = TreeDecorator::ObjectHanger.new(events)
hanger.outer {|content| content_tag('ul', content.html_safe)}
hanger.inner {|content| content_tag('li', content.html_safe)}
hanger.element {|event| link_to(event.title.html_safe, event_path(event))}
hanger.tree
end
That then gives me my nested ordered list, and it is then trivial to make it dynamic:
<%= events_in_unorder_list(@event_roots) %>
</div>
<%= javascript_tag('$(".events").dynatree({});') %>