Donato
Donato

Reputation: 2777

rendering text and html in a block of content_tag

I am trying to produce the following html using rails helpers in a helper file:

<span class="btn btn-default btn-file">
  Browse File<%= file_field_tag :file %>
</span>
<input type="text" class="form-control file-display" placeholder="" style="width: 250px; display: inline">

This is what I tried:

def file_helper(form, attr)
  span = content_tag :span, class:"btn btn-default btn-file" do
    "Browse File" + form.file_field(attr)
  end
  input = content_tag(:input, nil, type: 'text', class:"form-control file-display",   style:"width: 250px; display: inline")
  span + input
end

<%= file_helper f, :document %>

Unfortunately the resulting html looks like this:

<span class="btn btn-default btn-file">Browse File&lt;input id="document_document" name="document[document]" type="file" /&gt;</span>
<input class="form-control file-display" style="width: 250px; display: inline" type="text">

The problem is the nested input of the span is not rendered as html. It is rendered as text along with "Browse File". How can I get the "Browse File" to render as text and the input to render as html within the outer span?

Upvotes: 1

Views: 2279

Answers (2)

Aventuris
Aventuris

Reputation: 630

You're running into an issue when combining "safe" Strings which are wrapped by a SafeBuffer and unsafe strings which aren't.

SafeBuffer inherits from String, overriding +, concat and << so that:

  • If the other String is safe (another SafeBuffer), the buffer concatenates it directly
  • If the other String is unsafe (a plain String), the buffer escapes it first, then concatenates it

(source: click)

In your case form.file_field(attr) yields a proper safe buffer but "Browse File" does not. As a result, when they are combined, they are now a regular String, not wrapped by a SafeBuffer.

In the last line, you again combine a properly wrapped String input with the previous unwrapped String span which leads to span being escaped.

.html_safe creates a SafeBuffer wrapper for a String so wrapping "Browse File".html_safe + form.file_field(attr) should do the trick.

Upvotes: 2

Leantraxxx
Leantraxxx

Reputation: 4596

Try (span + input).html_safe Check this out...

Upvotes: 0

Related Questions