Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

deeply nested content_tag, concat and rails 3

I'm frustrated using Rails 3.2 and making a helper for Bootstrap modals. I don't understand when you need concat versus when you don't sometimes I end up with tags missing and sometimes I end up with a hash with all the options between before and ending tags. When I use concat on any content-tag with a do-end all hell breaks loose. All I want to do is replicate this html:

<div id="stupid_modal" class="modal hide fade" tabindex="-1" data-width="760">
    <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fontello-icon-cancel-1"></i></button>
        <h4>Modal header</h4>
    </div>
    <div class="modal-body">
        <div class="page-header">
            <p>Test header 1 2 3.</p>
        </div>
        <div class="row-fluid">

           content here... blah blah

        </div>
    </div>
    <div class="modal-footer">
        <button type="button" data-dismiss="modal" class="btn">Close</button>
        <button type="button" class="btn btn-green">Save changes</button>
    </div>
</div>

I cannot for the life of me get the button in the h4 in the modal header to work out right. Neither can I get the page header to appear in the modal body.

My helper looks like this:

module ModalHelper
def modal(css_id, header_text, hidden = true, options = {},&block)
    class_text = "modal"
    class_text += " hide fade" if hidden
    content_tag(:div, :class => 'modal hide fade', :id => css_id, :style => ("display:none;" if hidden)) do 
        concat modal_header(header_text)
        concat modal_body(&block)
        concat modal_footer
    end
end

def modal_button(link_text, href)
    modal_caller link_text, href, :button
end

def modal_link(link_text, href)
    modal_caller link_text, href
end

private

def modal_caller(link_text, href, type = nil)
    options = { :"data-toggle" => "modal" }
    options.merge!({ :class => "btn" }) if type == :button
    link_to link_text, "#" + href, options
end

def modal_header(header_text)
    content_tag(:div, :class => 'modal-header') do
        concat content_tag(:button,(content_tag(:i, :class => 'fontello-icon-cancel-1')),:class => 'close', :"data-dismiss" => 'modal', :"aria-hidden" => 'true')
        concat content_tag(:h4, header_text)
    end
end

def modal_body(page_header = "")
    content_tag(:div, :class => 'modal-body') do
        content_tag(:div, :class => 'page-header') do
            concat content_tag(:p, page_header)
        end
        content_tag(:div, :class => 'row-fluid') do
            yield
        end
    end     
end 

def modal_footer
    content_tag(:div, :class => 'modal-footer') do
        concat content_tag(:button, 'Close', type: "button", :class => 'btn btn-boo', :"data-dismiss" => 'modal')
        concat content_tag(:button, 'Save', type: "button", class: 'btn btn-green')
    end     
end 

end

And the link looks like this:

<%= modal_link "New Stupid Modal", "stupid_modal" %>

And the modal html looks like this:

<%= modal('stupid_modal', 'Shouldnt this work?', submit: true, tabindex: '-1') do %>
    <% render 'stupid_modal_partials/stupid_modal' %>
<% end %>

The output is this:

<button aria-hidden="true" class="close" data-dismiss="modal"><i>{:class=&gt;&quot;fontello-icon-cancel-1&quot;}</i></button>

which looks like this in the page source:

<i>{:class=>"fontello-icon-cancel-1"}</i>

Update:

changing modal_header to this works:

def modal_header(header_text)
    content_tag(:div, :class => 'modal-header') do
        concat content_tag(:button,(content_tag(:i, "",:class => 'fontello-icon-cancel-1')),:class => 'close', :"data-dismiss" => 'modal', :"aria-hidden" => 'true')
        concat content_tag(:h4, header_text)
    end
end

But this doesn't:

def modal_header(header_text)
    content_tag(:div, :class => 'modal-header') do
        concat content_tag(:button,:class => 'close', :"data-dismiss" => 'modal', :"aria-hidden" => 'true') do
            concat content_tag(:i, "",:class => 'fontello-icon-cancel-1')
        end
        concat content_tag(:h4, header_text)
    end
end

which begs the question, wzup with concat? and am i missing something -- I also tried empty quotes as the second argument to the button content_tag

like image 512
Michael K Madison Avatar asked Dec 09 '22 16:12

Michael K Madison


1 Answers

You don't need to ever use concat.

Each Rails helper returns a string with some html in it:

tag(:br) # "<br>"

So your simplest helper method would be this:

# "<br>"
def br
  tag(:br)
end

If you have multiple strings of html just sum them up:

# "<button>Close</button><button>Save</button>"
def modal_buttons
  content_tag(:button, "Close") + content_tag(:button, "Save")
end

Note that you can't just call them as they don't modify the view

# "<button>Save</button>"
def modal_buttons
  content_tag(:button, "Close") # this won't do anything
  content_tag(:button, "Save")
end

For blocks the same rules apply:

# "<div><button>Close</button><button>Save</button></div>"
def modal_footer
  content_tag(:div) do
    # what block returns will be inside the div
    content_tag(:button, "Close") + content_tag(:button, "Save")
  end
end

def modal_body
  content_tag(:div) do
    modal_header + yield + modal_footer
  end
end

As a side note, using just Rails helpers to construct the whole view isn't really their intended purpose. They are supposed to help you in dynamic places, static html is better done in ERB templates.

like image 136
Simon Perepelitsa Avatar answered Dec 11 '22 07:12

Simon Perepelitsa