Rails + Bootstrap: Render partial with locals in Bootstrap popover - ruby-on-rails

I want to pass a local variable to my partial when I render it in a Bootstrap popover. Here's what I've got, though I'm pretty sure I'm not rendering the partial correctly in the content_tag.
<%= content_tag :button, type: "button", class: "btn btn-default",
:data => { container: "body", toggle: "popover", placement: "bottom",
content: "#{render 'layouts/quick_add_form', :locals => {:code => item1.code}}"} do %>
button
<% end %>
Any help is much appreciated!
EDIT
Currently the local variable is not being passed to the partial, and so the :code attribute is not saved on form submit.

I don't believe you can use #{} except in HAML (oh wait, I see #{} is used as regular Ruby string interpolation - I think it will work). Not only that, but when you call render on a partial and you want to pass additional values, for some reason (for some versions of Rails), you have to explicitely declare it a partial:
render partial: 'layouts/quick_add_form', :locals => {:code => item1.code}
That will work, at least in an ERB or HAML.
You should also verify the generated HTML is escaped properly in the data attribute by viewing CTRL-U source in the browser.

Related

Why is this block not working on my ERB template

<%= render layout: "shared/some_template",
locals: {
variable_value: true
} do %>
<%= hidden_field_tag "ids[]", "ng-value": "sth.id" %>
<% end %>
The template on some template has some html and a yield call where the "hidden" field should go but it's not rendering it, it does render everything else inside the template, it just drops the hidden_field_tag part.
Any idea how can I solve this? it works on the HAML version when I tried it, but not on ERB, is that not available for ERB?
You are passing a &block to render, which is doing nothing with it.
To pass a callback to a partial, build a lambda and put it in a local variable:
<%=
lamb = lambda{ hidden_field_tag 'ids[]', 'ng-value' => 'sth.id' }
locals = { variable_value: true, callback: lamb }
render layout: 'shared/some_template', locals: locals
%>
Now inside the template call <%= callback.call %>.
(Note, BTW, that I used ' instead of ", because we are not using the special features of ". And note I introduced a local variable, locals, instead of creatively indenting the render call.)

Displaying validation errors with Ruby

I'm having some trouble rendering validation messages using "remote => true"
I have a partially rendered form for saving an address
<%= render :partial => "registrations/address", :locals => {:address => #user.customer_addresses.build, :is_new => true, :checked => false} %>
In this form, the user clicks this button to create a new address
<%= link_to "Save Address", "javascript://", :remote => true, :data => "new", "data-target" => create_user_address_url, "data-method" => "Post" %>
I have the 'create_address' function set up in the controller (which returns the validation errors), as well as a create_address.js.erb file. However, it doesnt seem like the browser is executing anything in the js file.
It would be great to see the code of js.erb file
But I assume you have escape javascript issue.
Just use j in your render partial method. E.g.
<%= j render('partial_name') %>
You might have forgot to reload the partial which show the error message. After using remote => true you need to reload the partial so that the changes will reflect on that partial.

RoR Class vs Instance variables, and relaying a value to partial

I have a controller "mainpage", with a correspondingly named view. The controller creates a #myLocalSuites variable, and the view includes the following line:
<li class="active"><%= link_to "Perforce", :action => 'renderp4', :remote => true, :localSuites => #myLocalSuites %></a></li>
Routing is defined such that clicking this link_to calls renderp4.js.erb to render a partial within the mainpage view:
$('#MainPage').replaceWith('<%= escape_javascript render "perforce_sync/perforceSync" %>')
where _perforceSync partial includes:
<%= select_tag "perforceSuites", options_for_select(*MYOPTIONSVARIABLE*), {:class => 'form-control', :size => "20", :multiple => true} %>
Where *MYOPTIONSVARIABLE* needs to be myLocalSuites as cascaded down from the mainpage view/controller.
Having tried everything I can think of, and failed - can someone please show how to modify the above snippets to use the required variable in the PerforceSync partial? Everything I've tried seems to produce something along the lines of:
ActionView::Template::Error (undefined method `map' for nil:NilClass):
An example of what I've tried. I don't think I'm a million miles off, but...
<li class="active"><%= link_to "Perforce", :action => 'renderp4', :remote => true, :localSuites => #myLocalSuites %></a></li>
$('#MainPage').replaceWith('<%= escape_javascript render "perforce_sync/perforceSync", :suitesLocally => params[:localSuites]%>')
<%= select_tag "perforceSuites", options_for_select(params[:suitesLocally]), {:class => 'form-control', :size => "20", :multiple => true} %>
Thanks! :)
In response to your comment, there are two things you can do here. One way is to simply render some dynamic JS on page load, and then use javascript to show that data at a later point.
If this data however is to depend on user actions after the page has loaded, you must make another request to the server using AJAX.
The first way might look like this:
<script>
var my_data = "<%= #some_data %>";
//#some_data could be set by the controller action for example
$('button').click(function() {
$('div.content_container').text(my_data);
});
</script>
The second way would look like this:
<script>
$('button').click(function() {
$.ajax({
url: '/some_resource/id.json',
data: {param1: 'some_user_data'}
}).done(function(data) {
$('div.content_container').text(data);
});
});
</script>
The data option for the ajax call allows you to pass parameters back to the server, so you can send some data provided by the client. Documentation for jquery ajax is here if you want to see other options.
The .done callback gets fired when the client receives a response from the server, and the function parameter is the data returned.

Pass Parameters in render - Rails 3

I've seen a couple questions on this but haven't been able to solve it...
I'm trying to pass a parameter while rendering a partial (similar to domainname.com/memory_books/new?fbookupload=yes)
Right now, I use this line:
<%= render :partial => '/memory_books/new', :fbookupload => "yes" %>
and in the partial, I have tried to get the content of fbookupload by using:
<%= fbookupload %>
which gives an "undefined local variable" error and
<%= params.inspect %>
which does not show fbookupload as a parameter.
How can I have the partial pass along the parameter :fbookupload?
Thank you.
UPDATE:
Could it have anything to do with the fact that I'm rendering this within a render?
i.e. the page (/fbookphotos/show) that has
<%= render :partial => '/memory_books/new', :fbookupload => "yes" %>
is being rendered by another page with (posts/show) via:
<%= render :partial => '/fbookphotos/show' %>
so I'm rendering this within a render.
try this:
<%= render :partial => '/memory_books/new', :locals => {:fbookupload => "yes"} %>
Taking it out of the comments for posterity. This syntax is correct:
render '/memory_books/new', fbookupload: "yes"
But if there is a reference to rendering the same partial without specifying the local variables, e.g.
render '/memory_books/new'
then fbookupload variable becomes unavailable. The same applies to multiple local variables, e.g.
render 'my_partial', var1: 'qq', var2: 'qqq'
will work if only occurs once. But if there is something like that somewhere else in the code
render 'my_partial', var1: 'qq'
then the var2 will become unavailable. Go figure ...
To do it your way:
In the main view:
<% fbookupload = "yes" %>
<%= render :partial => '/memory_books/new', :locals => {:fbookupload => fbookupload} %>
And in the partial:
<%= fbookupload %>
2nd option:
Ideally in the controller, otherwise in the view, define an instance variable: #fbookupload = "yes". Then it is available everywhere. The partial will then be : <%= #fbookupload %>
Params is just request parameter, so if u want to pass it in params u have to add it to your url ?fbookupload=yes or assign it params[:fbookupload] = "yes", but i don't think that is a good idea.
But if u need to use params[:fbookupload]', u can replace it withparams[:fbookupload] || fbookupload', and pass fbookupload in locals hash for partial.
render can be called with or without the partial param, and there seems to be some confusion around the differences between these two forms.
The following two are equivalent:
<%= render "my_partial', my_param: true %>
and:
<%= render partial: "my_partial', locals: { my_param: true } %>
The first is a shorthand that allows you to omit partial:. With this shorthand, local variables are also not nested under locals:. This is explained well in the documentation (see 'Rendering the default case').
In the two cases above, you would access my_param in the partial directly with my_param.
One other source of confusion is that if you render the partial somewhere without passing my_param, then the partial will fail when it tries to access it. To get around this, you can access the local with local_assigns[:my_param] instead of my_param, which will give you nil if the param is not defined instead of erroring, as described in this documentation. Another alternative is to use defined?(my_param) before accessing it.

Ruby on Rails 3: AJAX call not refreshing div with link_to

I am new to Ruby on Rails and i am working through a few example applications in the O'Reilly Head First Rails book. In one of the examples there is a page made up of three partials. The middle partial is a list of items. There is a link right below this section that, when clicked, should refresh the div containing that partial. The book is running examples based off of Rails 2.3 i believe and i am using Rails 3.1. This is the example that the book is giving me:
routes.rb:
map.connect '/flights/:flight_id/seats', :action=>'flight_seats', :controller=>'seats'
seats_controller.rb:
def flight_seats
#flight = Flight.find(params[:flight_id])
render :partial => "flights/seat_list", :locals => {:seats => #flight.seats}
end
show.html.erb:
<div id="seats">
<%= render :partial=>"seat_list". :locals=>{:seats=>#flight.seats} %>
</div>
<$= link_to_remote("Refresh Seats", :url=>"/flights/#{#flight.id}/seats", method=>"get", :update=>"seats") %>
This example is also using prototype.js since that's what Rails 2.3 came with built in. Rails 3 has jQuery as the default JavaScript library. (not sure if that makes a big difference)
Here is what i have so far. This is getting the contents of the partial correctly, it's just not updating the "seats" div after the AJAX call gets the partial. My code:
routes.rb:
match 'flights/:flight_id/seats' => 'seats#flights_seats'
seats_controller.rb:
def flights_seats
#flight = Flight.find(params[:flight_id])
render :partial => "flights/seat_list", :locals => { :seats => #flight.seats }
end
show.html.erb:
<div id="seats">
<%= render :partial => 'seat_list', :locals => { :seats => #flight.seats } %>
</div>
<%= link_to "Refresh Seats", "/flights/#{#flight.id}/seats", :remote => true %>
Any idea why my <div id="seats"> won't refresh with the updated partial? I'm betting there is but i'll ask anyway, is something wrong with my code?
The :remote => true option is a bit weird if you aren't returning JSON data. You can wrap your HTML in a JSON object, though, which is what I typically do. Or if you want something closer to your existing code something like this should work for you:
<%= link_to "Refresh Seats", "/flights/#{#flight.id}/seats", :class => "refresh-seats" %>
In your javascript somewhere:
$(document).delegate(".refresh-seats", "click", function(e){
e.preventDefault();
$("#seats").load(this.href);
});

Resources