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

¿Fue útil?

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top