如何构建嵌套菜单“树”在 HAML 中

发布于 2024-08-24 16:33:53 字数 2075 浏览 3 评论 0原文

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

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

感觉我应该能够很容易地完成这个任务,而无需在 html 中手动编写标签,但我不是最擅长递归的。以下是我目前提出的代码:

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

View

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

...因此它在全球范围内正确缩进。

感谢您的帮助, 槊

I am trying to build a simple nested html menu using HAML and am not sure how to go about inserting the elements with the correct indentation, or the general best way to build nested trees. I would like to be able to do something like this, but infinitely deep:

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

It feels like I should be able to accomplish this pretty easily without resorting to writing the tags by hand in html, but I'm not the best with recursion. Here is the code I've currently come up with:

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

View

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

Sample YAML defining Menu

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

Any ideas how to do that so the output is like this:

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

...not like this:

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

... and so it's properly indented globally.

Thanks for the help,
Lance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

度的依靠╰つ 2024-08-31 16:33:53

Ruby 生成的 Haml 代码的缩进良好的技巧是 haml_tag 助手。以下是我将 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

The trick to nicely-indented, Ruby-generated Haml code is the haml_tag helper. Here's how I'd convert your menu_tag method to using 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
傲鸠 2024-08-31 16:33:53

类似这样的事情怎么样:

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

How about something along the lines of:

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
软的没边 2024-08-31 16:33:53

太棒了,@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

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

干杯。

Awesome, @shingara's hint put me in the right direction :). This works perfectly:

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

If somebody can make that even shorter, or make it more easy to customize the attributes on the nested nodes, I'll mark that as correct instead of this.

Cheers.

咋地 2024-08-31 16:33:53

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

It's because you send a pur HTML by your helper. The indentation become with HAML. You can can generate some HAML in your helper.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文