¿Cómo construir menús anidados “árboles” en HAML
Pregunta
Estoy tratando de construir un menú simple html anidada utilizando HAML y no estoy seguro de cómo ir sobre la inserción de los elementos con el correcta muesca , o la mejor manera general, para construir árboles anidados. Me gustaría ser capaz de hacer algo como esto, pero infinitamente profunda:
- categories.each_key do |category|
%li.cat-item{:id => "category-#{category}"}
%a{:href => "/category/#{category}", :title => "#{category.titleize}"}
= category.titleize
Se siente como yo debería ser capaz de lograr esto con bastante facilidad sin tener que recurrir a la escritura de las etiquetas a mano en html, pero no soy el mejor con la recursividad. Aquí está el código que he llegado actualmente con:
View Helper
def menu_tag_builder(array, &block)
return "" if array.nil?
result = "<ul>\n"
array.each do |node|
result += "<li"
attributes = {}
if block_given?
text = yield(attributes, node)
else
text = node["title"]
end
attributes.each { |k,v| result += " #{k.to_s}='#{v.to_s}'"}
result += ">\n"
result += text
result += menu_tag_builder(node["children"], &block)
result += "</li>\n"
end
result += "</ul>"
result
end
def menu_tag(array, &block)
haml_concat(menu_tag_builder(array, &block))
end
Ver
# index.haml, where config(:menu) converts the yaml below
# to an array of objects, where object[:children] is a nested array
- menu_tag(config(:menu)) do |attributes, node|
- attributes[:class] = "one two"
- node["title"]
Menú YAML Muestra definir
menu:
-
title: "Home"
path: "/home"
-
title: "About Us"
path: "/about"
children:
-
title: "Our Story"
path: "/about/our-story"
Alguna idea de cómo hacer eso por lo que la salida es la siguiente:
<ul>
<li class='one two'>
Home
</li>
<li class='one two'>
About Us
</li>
</ul>
... no de esta manera:
<ul>
<li class='one two'>
Home</li>
<li class='one two'>
About Us</li>
</ul>
... y por lo que está adecuadamente sangría a nivel mundial.
Gracias por la ayuda, Lanza
Solución
El truco para sangría bien-, código Haml generado por el rubí es la haml_tag
ayudante . Así es como me gustaría convertir su método menu_tag
a usar haml_tag
:
def menu_tag(array, &block)
return unless array
haml_tag :ul do
array.each do |node|
attributes = {}
if block_given?
text = yield(attributes, node)
else
text = node["title"]
end
haml_tag :li, text, attributes
menu_tag_builder(node["children"], &block)
end
end
end
Otros consejos
¿Qué tal algo a lo largo de las líneas de:
def nested_list(list)
return unless list
haml_tag :ul do
list.each do |item|
haml_tag :li do
haml_concat link_to item["title"], item["path"]
if item["children"]
nested_list item["children"]
end
end
end
end
end
impresionante, pista de @ Shingara me puso en la dirección correcta :). Esto funciona perfectamente:
def menu_tag(array, &block)
return "" if array.nil?
haml_tag :ui do
array.each do |node|
attributes = {}
if block_given?
text = yield(attributes, node)
else
text = node[:title]
end
haml_tag :li, attributes do
haml_concat text
menu_tag_builder(node[:children], &block)
end
end
end
end
Si alguien puede hacer que incluso más corto, o que sea más fácil de personalizar los atributos en los nodos anidados, yo marcaré que a medida correcta en lugar de esto.
Saludos.
Es porque se envía un HTML pur por su ayudante. La muesca se convierten con HAML. Puede puede generar algo de HAML en su ayudante.