customize kaminari pagination template - ruby-on-rails-3

I'm having difficulty customizing the default kaminari template.
I've used the generator to create kaminari template files. In kaminari/paginator.html.haml:
= paginator.render do
%nav.pagination
All I want to do is access the actionview helpers within this, like link_to, or render. I've searched the source code and I can't find any incline of the helper being passed to this render method.
Essentially, being able to do this:
= paginator.render do
%nav.pagination
= render :partial => 'custom links'
= link_to "custom link", custom_path
..would solve my problems.

I didn't get a satisfactory answer, and so I'll submit my own solution.
Helpers cannot be used in the paginator.render block.
So, first I generate kaminari custom template files:
rails g kaminari:views default -e haml
Create a new file kaminari/custom.html.haml with the contents:
#pagination
= paginate custom
= render :partial => "kaminari/custom_view_file"
Replace kaminari paginator helper (paginate #results) in your view file with:
= render :partial => "kaminari/custom", :object => #results

You should be able to do something like this:
# /app/views/kaminari/_paginator.html.erb
= paginator.render do
%nav.pagination
= render :partial => 'shared/custom'
= link_to "custom link", custom_path
Basically, you need to provide the full path of the partial as it probably does not reside in the same directory.
EDIT:
I think Kaminari does not import rails view helpers in the paginate.render block in _paginator.html.erb.
To customize the output generated by paginator, you should instead
1. customize the _next_page.erb.html and so on where you can use rails helpers. I don't know why it is so though.
2. If you want to display some common html as a part of paginator, I suggest you put it in layout instead. Paginator is about navigation of pages.
For example, this is the _prev_page.html.erb:
<span class="prev">
<%= link_to "google", "www.google.com" %>
<%# link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, :rel => 'prev', :remote => remote %>
</span>
I just commented out the old code and used a custom link.

Just met the same problem.
My solution:
= paginator.render do
%nav.pagination
= render :partial => 'custom links'
= #template.link_to "custom link", custom_path
As partial rendering occurs in scope of Paginator, there is possibility to use its instance variable, pointing to template (see https://github.com/amatsuda/kaminari/blob/master/lib/kaminari/helpers/paginator.rb)
Little hacky, but works.

Related

link_to Helper Modifications

Inside of a rails app that I am working, I modified the link_to helper slightly:
def link_to(*args, &block)
args[1] = params[:client_id].present? ? "#{args[1]}?client_id=#{params[:client_id]}" : args[1]
super
end
I did this so I wouldn't have to add the :client_id => params[:client_id] every time I wrote a link_to inside of the app. Well, I have kind of pigeon holed myself with the following problem...
If I have this link_to:
<%= link_to "Continue to billing info", add_product_path(:product_id => #product.id), :class => 'btn' %>
Using my link_to helper creates a link, like so:
http://localhost:3001/orders/add_product?product_id=35?client_id=HT274848772
I am at a slight loss on how to modify my helper so that the link will work as normal while including the :client_id param...
You want to add your parameter to the link url, not to the link itself. Maybe you should rewrite the url_for helper, which is the helper used by all of the url helpers ( http://apidock.com/rails/ActionView/Helpers/UrlHelper/url_for )

Render #object and locals vs render :partial

I want to pass a local variable that contains the origin to come on a specific page, this variable contains just a symbol with the value.
When I use this code it works perfect, the origin variable is accessible in the partial :
render :partial => "products", :collection => #products, :locals => {:origin => :gallery}
But when I use this code, the origin is not set and not accessible in the partial :
render #products, :locals => {:origin => :gallery}
What is the difference here? Is the second line of code not render the partial like the first line?
<%= render #products %>
Is indeed the shorthand syntax for rendering a partial. But with the shorthand syntax, Rails will ignore the ":locals" variable. There's more on this in the Rails Guides.
So if you want to pass extra options to the render, you have to specify ":partial => ...". If you want to know why this happens, you can take a look at the Rails source.
There's a good explanation here: Rails: confused about syntax for passing locals to partials
The short version is that you can just omit :locals in the second example:
render #products, :origin => :gallery

Is view_context no longer available in Rails 3 views?

in a current Rails 3.0.9 app of mine I had a few .js.erb templates that were using view_context in them so I could call fields_for on it during a ajax request. This was letting me build some nested attribute form fields via ajax. But upon upgrading to Rails 3.1 I'm getting the follow error:
ActionView::Template::Error (undefined local variable or method `view_context' for #<#:0x1057b9f70>):
Was this removed/deprecated recently? Is there another way I can build nested fields_for inputs without having the parent FormBuilder handy? It seems view_context is still available in the controller, but I was hoping to keep this markup generation in the View layer.
My .js.erb template looked like this
<% meal_item_fields = view_context.fields_for :meal_items, Meal.new.meal_items.new, :child_index => "new_meal_items" do |f|
render :partial => 'meal_items/meal_item_fields', :locals => {:meal_item_form => f}
end
%>
$("#meal-items").append("<%= escape_javascript(meal_item_fields) %>");
According to api docs it is deprecated in >= 3. Source of 3.0.9 returned self for view_context. I think if you were to try without view_context it would just work.
<% meal_item_fields = fields_for :meal_items, Meal.new.meal_items.new, :child_index => "new_meal_items" do |f|
render :partial => 'meal_items/meal_item_fields', :locals => {:meal_item_form => f}
end %>
$("#meal-items").append("<%= escape_javascript(meal_item_fields) %>");
You might want to add helper_method :view_context in your controller.

render :inline => "<%= yield %>" not working

I'm upgrading from Rails 2.3.8 to 3.0.3 and notice that my code for nested layouts isn't working.
In my main Application layout I have the line
<%= controller.sub_layout %>
which then looks to the controller, who has:
def sub_layout
render :inline => "<%= yield %>"
# or otherwise some partial for the sub-layout
end
The problem is, this doesn't get rendered! If I put a direct <%= yield %> statement in the layout, it does work. So the question is, what's happening here, and how do I fix it?
This worked beautifully in Rails 2.3.8
How about a much saner approach:
render :layout => false
Related: http://guides.rubyonrails.org/layouts_and_rendering.html#using-render
So you all have some more of a background on this, the whole sub-layout approach was based on this blog post: Sorta Nested Layouts (The solution is given in the comments section.)
Instead of making a controller method sub_layout, any controller that uses a sublayout needs to define a before_filter method that sets a variable:
def inner_layout
#inner_layout = 'layouts/sublayout_partial_name'
end
then in the main layout.html.erb (i.e. application.html.erb), where you would otherwise put your yield statement:
<%= #inner_layout ? render(:partial => "#{#inner_layout}") : yield %>
the assumtion is that the sublayout partial file will have its own yield statement in there somewhere.

What's the alternative of :before & :after of rails 2.3.* in Rails 3?

I am using remote form in Rails 3. It works fine but I want to show / hide spinner during ajax request.
In rails 2.3.* we use :before & :after in remote form to show/hide spinner
What should I do in Rails 3, as remote form of Rails 3 doesn't contain such options.
Here is a working solution I tried:
In my view file, I use :onSubmit to show a spinner:
<% form_for("", #search,
:url => {:action => "search"},
:html => {:id => "search_form",
:onSubmit => "$('search-loader').show();"},
:remote => true) do |f| %>
In my search action, I added one line to hide it:
render :update do |page|
...
page << "$('search-loader').hide();"
end
It works great..!
Well, I'm using jQuery, and I'm doing the following, trying to be unobtrusive:
Add this, right before your </head> tag:
= yield :document_ready
Then in your application_helper.rb:
def document_ready(content)
html = %{ $(function(){#{content}})}
content_for(:document_ready){ javascript_tag(html) }
end
This allows you to load and run javascript once your document is loaded.
On top of the view containing your form add:
- document_ready("hide_button_show_spinner('your_button_id')")
In application.js
function hide_button_show_spinner(element_id) {
$('#'+element_id).bind('click', function() {
$('#'+element_id).after("<img src='/path/to/your/spinner.gif' class='ajax_loader' id='"+element_id+"_ajax_loader' style='display: none'/>")
$('#'+element_id).hide();
$('#'+element_id+'_ajax_loader').show();
});
}
This will hide the button and show the spinner once the button is clicked. You may need to adapt this to your specific case.
You can then show the button and hide the spinner in your javascript response (the .js.erb file that you render from the action called by the ajax request).