Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to generate full ul/li tree with walk_tree? #69

Open
spacerobotTR opened this issue Oct 5, 2017 · 6 comments
Open

How to generate full ul/li tree with walk_tree? #69

spacerobotTR opened this issue Oct 5, 2017 · 6 comments
Labels

Comments

@spacerobotTR
Copy link

Sorry if this is the wrong place for this but how would you take this example:

<% Page.walk_tree do |page, level| %>
<%= link_to "#{'-'*level}#{page.name}", page_path(page) %>

<% end %>

And turn this into a

  • list with items? I am trying to use this with jstree to output the tree view.

@felixbuenemann
Copy link
Collaborator

felixbuenemann commented Oct 6, 2017

I don't think walk_treeis useful for that case.

You could create a recursive view helper to generate the html.

Another approach would be to do it in ERB and recursively render a partial.

Something like this should work in a rails helper (untested):

def render_tree(nodes)
  return ''.html_safe if nodes.empty?
  content_tag(:ul) do
    nodes.map do |node|
      content_tag(:li) do
       link_to(page.name, page_path(node)) + render_tree(node.children)
      end
    end.join.html_safe
  end
end

Then in you view you could do:

<%= render_tree(Page.roots) %>

@spacerobotTR
Copy link
Author

Thank you I will play around with this.

@spacerobotTR
Copy link
Author

spacerobotTR commented Nov 5, 2019 via email

@fathur-bookdoc
Copy link

@spacerobotTR thanks your snippet really helpful :)

@felixbuenemann
Copy link
Collaborator

felixbuenemann commented Nov 5, 2019

It looks like @spacerobotTR's solution depends on a fixed depth.

A more versatile approach would be to recursively render a partial for each nesting, passing the children as data to the partial.

Example:

<%# app/views/documents/_tree.html.erb %>
<ul>
  <%= render partial: :node, collection: Document.roots.preload(:children) %>
</ul>
<%# app/views/documents/_node.html.erb %>
<li>
  <%= node.name %>
  <%- unless node.leaf? -%>
  <ul>
    <%= render partial: :node, collection: node.children.preload(:children) %>
  </ul>
  <%- end -%>
</li>

@fathur-bookdoc Please let me know how this works for you, we could add an example to the README to help others in the future.

Update: Slightly tweaked the example to use #preload(:children) to avoid needless count queries and reduce n+1 queries.

@spacerobotTR
Copy link
Author

That is great and a better way to load these. I'm glad you revisited this. I was going to come back to functionality shortly for a new project I am working on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants