rabid_zombie
rabid_zombie

Reputation: 992

form_for in content_tag block

I have this function in module MessagesHelper:

def message_block( message, ticket, comment )
  content_tag( :div, :class => "message", :id => "message-" + message.id.to_s ) do
    content_tag( :p, message.body, :class => "message-body", :id => "message-body-" + message.id.to_s ) +

    content_tag( :div,  content_tag( :a, "add comment", :id => "comment-link-" + ticket.id.to_s, :class => "comment-link" ), :id => "comment-" + ticket.id.to_s, :class => "comment" ) +

    form_for( comment, :html => { :class => "add-comment", :id => "add-comment-" + ticket.id.to_s } ) do |f|
      f.label :body, "add comment"
      f.text_area :body
      f.submit "add comment"
    end
  end
end

To get this expected outcome:

<div class="message">
  <p></p>
  <div class="comment">
  </div>
  <form class="add-comment">
  </form>
</div>

In my partial view, _messages.html.erb:

<% if [email protected]? %>
  <% @message.each do |m| %>
  <%= message_block( m, @ticket, @comment ) %>
<% end %>

The text_area does not even load in the DOM and I can only see the add comment button. This is all in the TicketController (not MessageController or CommentController).

Any help with my problem would be great. Thank you.

Upvotes: 1

Views: 1353

Answers (2)

Zhao Li
Zhao Li

Reputation: 5696

I think I just came across this same issue. What I found out is helpers only return a string. Hence the last output generated by 'f.submit "add comment"' in your helper is what's returned and gets put into your view template. To work around this, you'll need to concatenate all your string outputs and return that large string at the end of your helper. Hope this addresses your question.

I think this is the convention to limit helpers to single outputs. Because otherwise, partials are probably the way to go.

Take care!

Upvotes: 2

jdoe
jdoe

Reputation: 15771

You've got a quite hard to read and maintain helper. I would suggest you to consider usage of partial for it.

Here's the example. Let's say you want to render a lot of forms and you consider to create a helper which accepts some header, object for form and list of fields to be included in the form. Here the solution via partials.

Create in your views/shared/_render_some_stuff.erb (note the underscore at the beginning):

<%= title %>
<%= form_for object do |f| %>
    <% fields.each do |field_name| %>
        <%= f.label field_name %>
        <%= f.text_field field_name %>
    <% end %>
<% end %>

And "inject" it in any view this way:

<%= render 'shared/render_some_stuff', 
            title: 'Hello', object: Product.first, fields: [:title, :price] %>

(Note: here no underscore at the beginning. You just need it to distinguish your partial in a directory, but not here)

I guess it beats your approach?

Upvotes: 1

Related Questions