The project I'm working on requires some of the data table's column titles to be referenced/defined in a footnote below the table.
As it's dynamic content that will be looped over depending on how many of the column titles require footnotes, I need to handle most of this in via models/helpers. I have been able to replicate the html our US designer wants using content_tag
, but rubocop is whining about the use of content tag and says I should be using tag
instead. But I can't get the nesting of the html tags to work at all using the tag
method.
The section html I'm trying to produce is this (which will be repeated for as many footnotes are needed):
<li id="id" class="p-2">
<dl class="m-0"><dt class="d-inline">Unusual term: </dt>
<dd class="d-inline">Text with the definition of the term.<a href="#id-ref" aria-label="Back to content">↵</a></dd>
</dl>
</li>
And the content_tag
based code that works to produce it is this:
content_tag(:li,
content_tag(:dl, [
content_tag(:dt, 'Unusual term: ', class: "d-inline"),
content_tag(:dd, [
'Text with the definition of the term.',
content_tag(:a, '↵', href: '#id-ref', aria: { label: "Back to content" })
].join.html_safe, class: "d-inline")
].join.html_safe, class: "m-0"),
id: 'id',
class: "p-2")
When I switch to using tag
, the problem I'm coming up against is getting both the <dt>
and <dd>
tags, which both have content, to nest inside the <dl>
tag (and also the <a>
tag, which also has content, to nest within the aforementioned <dd>
tag). The tag
method only seems to output the last piece of nested content and ignores any other content that precedes it.
This is the nesting of the tag method that I've tried:
tag.li id: 'id', class: 'p-2' do
tag.dl class: 'm-0' do
(tag.dt 'Unusual term: ', class: 'd-inline') +
(tag.dd 'Text with the definition of the term.', class: 'd-inline' do
(tag.a arrow, href: anchor, aria: { label: 'Back to content' })
end)
end
end
And this is the output it's giving me.
<li id="id" class="p-2">
<dl class="m-0"><dt class="d-inline">Unusual term: </dt>
<dd class="d-inline"><a href="#id-ref" aria-label="Back to content">↵</a></dd>
</dl>
</li>
As you can see, it's close, but it's missing the text content of the <dd>
tag, which should be output just before the <a>
tag starts.
Can anyone help? Is there a way to nest tags without losing content? Or should I just give up and write a partial with the actual html code written out...?
I have now worked out a way to nest these tag methods to achieve the desired html output, using the following code:
link = link_to ' ↵', '#id-ref', aria: { label: 'Back to content' }
tag.li(id: 'id', class: 'p-2') do
tag.dl(class: 'm-0') do
(tag.dt 'Unusual term: ', class: 'd-inline') +
(tag.dd ('Text with the definition of the term.' + link).html_safe, class: 'd-inline')
end
end
If anyone has an alternative solution, I'd love to hear it, but I think this will serve for now.
EDIT TO ADD NEW SOLUTION
Thanks to @max suggestion of using concat
to rid me of #html_safe
I now have a block of code that I, my ux designer and rubocop will all be happy with! Here it is:
tag.li(id: 'id', class: 'p-2') do
tag.dl(class: 'm-0') do
tag.dt('Unusual term:', class: 'd-inline') + ' ' +
tag.dd(class: 'd-inline') do
concat 'Text with the definition of the term.'
concat tag.a(' ↵', href: '#id-ref', aria: { label: 'Back to content' })
end
end
end
Thanks again for everyone's input on my question. I really appreciate it.