This is how it will look used with a layout:
<%= sidebar %>
It generates:
<aside id="sidebar">
<div>hello</div>
</aside>
Features
- It knows how to close tags according to HTML5 spec (1)
- It accepts content as first argument (2)
- It accepts builder as first argument (3)
- It accepts content as block which returns a string (4)
- It accepts content as a block with nested markup builders (5)
- It builds attributes from given hash (6)
- it combines attributes and block (7)
# 1
html.div # => <div></div>
html.img # => <img>
# 2
html.div('hello') # => <div>hello</div>
# 3
html.div(html.p('hello')) # => <div><p>hello</p></div>
# 4
html.div { 'hello' }
# =>
#<div>
# hello
#</div>
html.div do
p 'hello'
end
# =>
#<div>
# <p>hello</p>
#</div>
# 6
html.div('hello', id: 'el', 'data-x': 'y') # => <div id="el" data-x="y">hello</div>
# 7
html.div(id: 'yay') { 'hello' }
#<div id="yay">
# hello
#</div>
It supports complex markup constructs, without the need of concatenate tags. In the following example, there are two div
tags that we don’t need link together.
The result is a very clean Ruby API.
The API is really simple: #tag
must be used for a self-closing tag, where #empty_tag
does the opposite.
html.tag(:custom, 'Foo', id: 'next') # => <custom id="next">Foo</custom>
html.empty_tag(:xr, id: 'next') # => <xr id="next">
Link helpers
The link_to
helper, while appearing similar to tags generated by html
, has different semantics and will not appear as part of the generator, as one might expect.
Since the return value of link_to
is a string, it must be treated as such when combined with the generator offered by html
.
Alone in a tag, the return value of link_to
can be used as the content for the tag.
html.div do
link_to('hello', routes.root_path, class: 'btn')
end
# => <div>
# => <a href="/" class="btn">hello</a>
# => </div>
html.div do
link_to('Users', routes.users_path, class: 'btn') +
link_to('Books', routes.books_path, class: 'btn')
end
If you require multiple link_to
inside the same tag, and there are other tags inside that tag, the return value of link_to
will need to be passed to one of the html generator helpers.
This might be a block or inline tag such as div
or span
, but if no wrapping element is desired, the text
helper can be used to render the link as-is.
The tag contents are automatically escaped for security reasons:
html.div('hello') # => <div>hello</div>
html.div { 'hello' } # => <div>hello</div>
html.div(html.p('hello')) # => <div><p>hello</p></div>
end # => <div><p>hello</p></div>
html.div("<script>alert('xss')</script>")
# => "<div><script>alert('xss')</script></div>"
html.div { "<script>alert('xss')</script>" }
# => "<div><script>alert('xss')</script></div>"
html.div(html.p("<script>alert('xss')</script>"))
# => "<div><p><script>alert('xss')</script></p></div>"
html.div do
p "<script>alert('xss')</script>"
end
# => "<div><p><script>alert('xss')</script></p></div>"
HTML attributes aren’t automatically escaped, in case we need to use a value that comes from a user input, we suggest to use #ha
, which is the escape helper designed for this case. See for a deep explanation.
View Context
module Web
module Views
module Books
class Show
include Web::View
def title_widget
html.div do
h1 book.title
end
end
end
end
end
end
<div id="content">
</div>