【问题标题】:How to build nested menu "trees" in HAML如何在 HAML 中构建嵌套菜单“树”
【发布时间】:2010-03-11 07:00:04
【问题描述】:

我正在尝试使用 HAML 构建一个简单的嵌套 html 菜单,但不确定如何使用 correct indentation 插入元素,或者构建嵌套树的一般最佳方法。我希望能够做这样的事情,但无限深:

- categories.each_key do |category|
    %li.cat-item{:id => "category-#{category}"}
        %a{:href => "/category/#{category}", :title => "#{category.titleize}"}
            = category.titleize

感觉我应该能够很容易地完成这项工作,而无需在 html 中手动编写标签,但我并不是最擅长递归的。这是我目前想出的代码:

查看助手

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

查看

# 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"]

定义菜单的示例 YAML

menu:
  -
    title: "Home"
    path: "/home"
  -
    title: "About Us"
    path: "/about"
    children: 
      -
        title: "Our Story"
        path: "/about/our-story"

任何想法如何做到这一点,所以输出是这样的:

<ul>
  <li class='one two'>
    Home
  </li>
  <li class='one two'>
    About Us
  </li>
</ul>

...不是这样的:

<ul>
<li class='one two'>
Home</li>
<li class='one two'>
About Us</li>
</ul>

...所以它在全局范围内正确缩进。

感谢您的帮助, 兰斯

【问题讨论】:

    标签: ruby recursion haml tree


    【解决方案1】:

    良好缩进的 Ruby 生成的 Haml 代码的诀窍是 haml_tag helper。以下是我将您的 menu_tag 方法转换为使用 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
    

    【讨论】:

      【解决方案2】:

      这样的事情怎么样:

      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
      

      【讨论】:

      • 这是 haml_concat 的绝妙用法,我能够在大约五分钟内使这项技术在我的应用程序中运行。非常感谢!
      【解决方案3】:

      太棒了,@shingara 的提示让我朝着正确的方向前进 :)。这非常有效:

      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
      

      如果有人可以让它更短,或者更容易自定义嵌套节点上的属性,我会将其标记为正确而不是这个。

      干杯。

      【讨论】:

        【解决方案4】:

        这是因为你的助手发送了一个纯 HTML。缩进变成了 HAML。您可以在 helper 中生成一些 HAML。

        【讨论】:

        • 实际上不可能在帮助程序中生成 Haml 代码并将其动态呈现为 HTML(除非您手动调用 Haml 编译器)。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-02-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-17
        相关资源
        最近更新 更多