-
Notifications
You must be signed in to change notification settings - Fork 463
Nested HTML from the arrange method
Joost Baaij edited this page Aug 24, 2018
·
2 revisions
You will need a helper:
module AncestryHelper
# Recursively render a partial from an Ancestry arranged subtree.
def arranged_tree_table_rows(tree)
tree.each do |node, children|
concat render partial: 'tree_node', object: node
arranged_tree_table_rows(children) if children.present?
end
end
end
As you would expect, put the subtree in a controller:
class SomeController < ApplicationController
def index
@subtree = TreeNode.find_by_name('Crunchy').subtree.arrange
end
end
and render it all in the corresponding view:
<% arranged_tree_table_rows(@subtree) %>
If you have a need to render your ancestry tree of any depth you can use the following helper to make it so. The Helper takes some options, mostly for styling. There is an option for sorting the tree by the current level (or group) we are in.
Note: This helper should not care about filtering or children depth. That should be handled via the normal ancestry methods before arrange() is called.
Secondary Note: This helper also assumes you are using the has_ancestry :cache_depth => true
option. If you are not using this, remove the references in the helper to ancestry_depth
.
#### Configuration options
:list_type # the type of list to render (ul or ol)
:list_style # this is used for setting up some pre-formatted styles. Can be removed if not needed.
:ul_class # applies given class(es) to all parent list groups (ul or ol)
:ul_class_top # applies given class(es) to parent list groups (ul or ol) of depth = 0
:ul_class_children # applies given class(es) to parent list group (ul or ol) of depth > 0
:li_class # applies given class(es) to all list items (li)
:li_class_top # applies given class(es) to list items (li) of depth = 0
:li_class_children # applies given class(es) to list items (li) of depth > 0
:sort_by # sort the hash by attributes of your ancestry object e.g. [:name] or [:order, :name]
# app/helpers/ancestry_helper.rb
module AncestryHelper
# arranged as tree expects 3 arguments. The hash from has_ancestry.arrange() method,
# options, and a render block
def arranged_tree_as_list(hash, options = {}, &block)
options = {
:list_type => :ul,
:list_style => '',
:ul_class => [],
:ul_class_top => [],
:ul_class_children => [],
:li_class => [],
:li_class_top => [],
:li_class_children => [],
:sort_by => []
}.merge(options)
# setup any custom list styles you want to use here. An example is excluded
# to render bootstrap style list groups. This is used to keep from recoding the same
# options on different lists
case options[:list_style]
when :bootstrap_list_group
options[:ul_class] << ['list-group']
options[:li_class] << ['list-group-item']
end
options[:list_style] = ''
output = ''
# sort the hash key based on sort_by options array
unless options[:sort_by].empty?
hash = Hash[hash.sort_by{|k, v| options[:sort_by].collect {|sort| k.send(sort)} } ]
end
current_depth = 0
# and here... we... go...
hash.each do |object, children|
li_classes = options[:li_class]
if object.depth == 0
li_classes += options[:li_class_top]
else
li_classes += options[:li_class_children]
end
if children.size > 0
output << content_tag(:li, capture(object, &block) + arranged_tree_as_list(children, options, &block).html_safe, :class => li_classes)
else
output << content_tag(:li, capture(object, &block), :class => li_classes).html_safe
current_depth = object.depth
end
end
unless output.blank?
ul_classes = options[:ul_class]
if current_depth == 0
ul_classes += options[:ul_class_top]
else
ul_classes += options[:ul_class_children]
end
output = content_tag(options[:list_type], output.html_safe, :class => ul_classes)
end
return output.html_safe
end
end
# Normally this variable would be set from the controller, but for examples sake
# Lets pretend we have a Category model that has_ancestry
@categories = Category.where({:active => true}).arrange
# simple ul > li structure
<%= arranged_tree_as_list(@categories) do |category| %>
# stuff that goes inside the <li></li> tags
<%= link_to category.name, category_path(category) %>
<% end %>
# use bootstrap styling, as setup in the helper
<%= arranged_tree_as_list(@categories, {:list_style => :bootstrap_list_group}) do |category| %>
# stuff that goes inside the <li></li> tags
<%= link_to category.name, category_path(category) %>
<% end %>
# sort by category name and then id
<%= arranged_tree_as_list(@categories, {:sort_by => [:name, :id]}) do |category| %>
# stuff that goes inside the <li></li> tags
<%= link_to category.name, category_path(category) %>
<% end %>