J Edward Ellis
J Edward Ellis

Reputation: 1348

How to add HTML markup programmatically in a Ruby on Rails view?

I am trying to return a formatted error message in the ActiveControler flash hash. This is rendered in my layout as:

<% flash.each do |name, msg| %>
    #<%= content_tag :p, msg, class: "flash #{name}" %>
<% end %>

When the msg = 'Bob' I get:

<p class="flash error">Bob</p>

Which displays as:

Bob

When the msg = '

  1. Bob
' I get:

<p class="flash error">"<ol><li>Bob</li></ol>"</p>

Which displays as:

<ol><li>Bob</li></ol>

What I want is to have it displayed as an ordered list of error messages.

I have also tried changing out the content_tag helper for straight hand coded markup and that doesn't change anything. I also tried replacing "<" and ">" with < and >. Of course that didn't help either. I know I can give up on this and write a custom error reporting page that behaves exactly as I want, but I was trying to do this in a simpler way.

Upvotes: 0

Views: 289

Answers (2)

J Edward Ellis
J Edward Ellis

Reputation: 1348

Anezio Campos suggests html_safe. After much research I chose to use sanitize with a white list of allowed tags instead. However, I still had a frustrating problem.

This code is being presented to the browser as HTML5. The problem appears in Chrome which is our projects only supported browser. I know that's a bad idea, but it's not my decision. Anyway if you look at the the W3 HTML Language Reference it says the ending paragraph tag is optional. Chrome placed my markup outside of the paragraph I was using to style the block!

So the final piece of the puzzle was to change from a paragraph tag to a div tag.

The result looks like:

<% flash.each do |name, msg| %>
      <% next if name.blank? || msg.blank? %>
    <div class="flash <%= name %>">
      <%= sanitize(msg, tags: %w(ol li)) %>
    </div>
<% end %>

Upvotes: 0

agmcleod
agmcleod

Reputation: 13621

Any reason you're using content tag right in the view when a regular tag works fine? Content tag is good for helper methods, so you can easily create html inside ruby code. Here's how i would do it in the view:

<% if flash.any? %>
<ol>
  <% flash.each do |name, msg| %>
    <li class="flash #{name}"><%= msg %></li>
  <% end %>
</ol>
<% end %>

Upvotes: 1

Related Questions