How do I render a partial view via its controller when loading a separate view in Ruby on Rails?
Thanks for your help in advance
Problem: I have a show.html.erb for my Patients controller, when this loads I have a series of tabs, one of which is a list of notes added to that patient record. Notes is a separate model. I want to load the list of notes when loading show.html.erb.
I can use the code below to render the view directly and can pass variables in this way, but I would rather go through the controller and deliver notes/_list.js.erb, via the Patients Controller.
<%= render "notes/list", :remote => true %>
I have a solution that loads the partial via a link_to but because the link is in a tab it then breaks my tab javascript, and would rather just load the information on initial page load rather than have the user interact with an element.
<%= link_to "Notes".html_safe,{:controller => "patients", :action => "notes", :remote => true } %>
It needs to be in a partial as I am then using pagy to paginate the results and if I display it via a controller dependent partial then the pagy navigation links function as expected.
Relevant Routes
get 'patients/:id/show' => 'patients#show', as: :show_patient
get 'patients/:id/notes' => 'patients#notes', as: :notes_patient
Relevant Patients Controller
def notes
#pagy, #notes = pagy( Note.where(:patient_id => params[:id]).reverse_order, items: 2 )
respond_to do |format|
format.html { render "notes/list" }
format.js { render "notes/list" }
end
end
notes/list.js.erb
$('#notes-list').html('<%= escape_javascript(render('notes/list')) %>');
notes/_list.html.erb
<% #notes.each do |note| %>
<%= render partial: note %>
<% end %>
<%== pagy_materialize_nav(#pagy) %>
<span class="pagy-info"><%== pagy_info(#pagy) %></span>
I believe you can do something like this in the controller:
# or whatever this partial is called
#notes_rendered = render_to_string "notes/list"
And then use it in the view you want.
Related
I have a search form. when i search for a record, the result goes to the show page as expected , but i want the result to render on the same page where ever i put the form partial
I want to create a partial that will render the show action on the same page with the form
Here is the shipment controller
class shipmentsController < ApplicationController
def show
#shipment = Shipment.find_by_trackCode(params["trackCode"])
unless #shipment.present?
end
......
Home controller index.html.erb
<%=render 'shipments/form' %>
Views/shipments/_form.html.erb
<%= form_tag search_path, :controller => 'shipments', :action => 'show', :method => 'get' do %>
<%= text_field_tag :trackCode %>
<%= submit_tag 'Track' %>
<% end %>
The present code will dispaly the result on the show page but I want the search result to be rendered using a partial so that i can render it where ever i use the form partial.
How can i archive that ?
are you really sure it's a good idea to use your show view as a partial? now if you are... you could rename your file _show.html.erb and reference it passing the folder name <%=render 'shipments/show' %> but you'd also have to change the loop to call the model Shipment.all.each instead of #shipment
render template: 'shipments/show', locals: {shipment: #shipment}
use variable shipment instead of #shipment in show.html.haml
I'm trying to render a the index view inside my ruby-on-rails application. How do a I render the index view, from inside a view passing an array of things to display? Using the link_to.
I do not want to re-route to the controller, I just want to link_to a view passing it the variables it needs, how can I do this?
EDIT:
I am trying to create a page type functionality in the index of my article model. So I have around 400 articles for example, and when the index action in the article controller is called, it of course renders the index view which is calling a partial for each article in the '#articles array' passed on by article controller's index action.
So in the view, I'm trying to do something like:
<% count = 0 %>
<% #articles.each do |article| %>
<% if count <10 %>
<%= render partial: 'index_articles', locals: {article: article} %>
<% count = count + 1 %>
<% end %>
<% end %>
<% #articles = #articles.drop(10) %>
<% if #articles.any? %>
<%= link_to "Next", 'articles', locals: {#articles => #articles} %>
<% end %>
Thank you in advanced for all of your help.
You'll need to use the render command, probably with a partial:
<%= render "controller/index", collection: ["your", "array"], as: :object_name %>
You will have to call a controller action to generate this. You cannot simply load it on your screen, unless it was preloaded inside your javascript for something:
#View
<%= link_to "Index", controllers_path(ids: ["1","2"]), remote: true %>
#app/controllers/your_controller.rb
class YourController < ApplicationController
def index
#posts = request.xhr? Post.find(params[:ids]) : Post.all
respond_to do |format|
format.js #-> app/views/controller/index.js.erb
format.html
end
end
end
#app/views/controller/index.js.erb
$(".element").html("<%=j render 'index' %>");
There are several issues with this approach...
Flow
First of all, your flow of your app should be as structured as possible.
In short, if you're calling the index view inside another action, it's not the index view any more.
What you should look at is how to use a partial in your app:
#app/controller/views/_partial.html.erb
<%= post.title %>
This way, you can adapt your index view and your other page to use the partial in their respective action layouts:
#app/controller/views/index.html.erb
<%= render "partial", collection: #posts, as: :post %>
This will allow you to "reuse" code much in the way you want. This will be much more appropriate than trying to invoke other action/views.
-
Resources
Secondly, you'll want to look at how your app functions.
Your index view is meant to show all the items for a particular object. Whilst you're free to change this as you want, the fact remains that you have to keep some structure.
You should read up on the routes for your actions, and how they're meant to work in your application. This will give you some perspective on the resourceful nature of Rails routes, and how you'll have to call specific routes with specific actions.
Your problem is probably that the file needs to be named _index.html.erb. You can have another file named index.html.erb which just renders _index.html.erb.
If you need a full guide on using AJAX, look up the railscast. If you're not using AJAX and you just want to render it, then you don't use link_to. You just do <%= render :index %>.
I have an index view for a model(nested ) that never gets called from the model, but is rendered from a couple different models. One view can render the index with either JS or html. With JS is it in a #related div in the show view and a data-remote link. Another option uses the same controller action to render it only has html.
All was fine until I added Kaminari paging. In the full page view, there was no #related div so paging didn't work. I broke out the guts into a partial and added a #related div and rendered the partial. From js I just rendered the partial from JS. That worked fine in the full page view, but in the show page it would render the partial, but the links didn't work, looks like it renders the entire show page. Clinking on another tab and then going back to the Progressions tab loads the partial and all works fine. It is just on the initial load of the show page that I can't get the page links to work.
I can load another tab that does not use paging first and solve my problem, but this was kind of the main information that you go to this page for.
Any ideas?
EDIT Request for code
The controller action method. The index method in this controller also sets #progressions
def progressions
authorize! :read, Progression
#stage = Stage.find(params[:id])
#progressions = #stage.progressions_by_score.page(params[:page]).per(20)
if params[:status] && !params[:status].blank? && #progressions
#progressions = #progressions.where(status: params[:status]).page(params[:page]).per(20)
end
respond_to do |format|
format.js
format.html {render :template => "progressions/index"}
end
end
The progressions.js.erb file in the stages view
$("#related").html("<%= escape_javascript(render('progressions/index'))%>");
The relations div in the show view. This is pretty much my scaffold template where I display or link to related information. The <div id="related"> is where any date-remote links will load the data. On initial load it loads the _index partial.
<div class="relations">
<span class="navspan">
<%= link_to 'Progressions: Status ->', progressions_stage_path(#stage), :'data-remote' => true,
:onclick => '$("#progression_status").val("")' %>
<span class="huh">
<%= hidden_field_tag :stage_id, params[:id]%>
<%= select_tag :progression_status, options_for_select(Progression.statuses["all"], params[:status]),
:prompt => 'All', :class => 'f-left' %>
</span>
<%= link_to 'Assessors', assessors_stage_path(#stage), :'data-remote' => true %>
<%= link_to 'Events', events_stage_path(#stage), :'data-remote' => true %>
<%= link_to 'Select', select_stage_path(#stage) if can? :select_candidates, #stage %>
<%= link_to 'Ad Mgmt', edit_ad_stage_path(#stage) if can? :manage_ad, #stage %>
</span>
<div class="f-clear"></div>
<div id="related">
<%= render "progressions/index"%>
</div>
</div>
The index.html.haml file
#related
= render "progressions/index"
The _index.html.haml file is just an index table listing the progressions but it does contain:
= paginate #progressions, :remote => true
Shortly after posting some code, I went back in my memory and used javascript to load the related div. I've tried to stay away from javascript, but in this case I added this to the end of the page after adding :id => "status_id" to the progressions link:
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
$("#status_link").trigger("click");
})
</script>
While this fixes my problem, I still don't understand why the initial html response does not respond to the page links in the related div. I'll leave that as something else to learn. I'll put it in coffescript after I figure out how to have fire only on initial load of the show page.
Suppose I have the following view in my rails app
<% if is_subscriber? %>
<%= render :partial => 'subscriber_page' %>
<% else %>
<%= render :partial => 'payment_form' %>
<% end %>
The payment form submits a post-rquest to the controller show page. In my routes file I have:
match ':users(/:id)', :to => 'users#submit_payment', :via => :post
My submit payment helper method is:
def submit_payment
current_user.is_subscriber = true
show
end
However when I run this I get a submit_payment template missing error. How can I make sure that the users show page is simply reloaded when the helper method is finished.
It looks like you're trying to redirect to the show page. Try this:
redirect_to user_path(#user) # Note you need to send the show page an :id param
If you're just wanting to render a specific partial, do this:
render :partial => 'show'
However, if you want something more seamless, like submitting the form VIA Ajax, which gets back a partial and then on success dumps it in to a waiting DIV or something, you can do that as well, though with a bit more complexity.
I'm new to rails and thought I had finally figured out some of this routing stuff, but have been going in circles with this bit all day.
I was following a tutorial about building a twitter like service, and I've got the basics working from the tutorial, but with Mongo instead of mySql.
I've got 3 types of pages.
The home page which is showing all the posts ordered by date
The user page which is showing the posts from a specific user
The posts page which is showing posts from a users friends.
So for each page, I've done the following
1) created a method in the corresponding controller to get the correct posts
2) created a _posts.html.erb page with the display parameters, which are slightly different on each page
3) referenced the partial in the index.html.erb page for each view.
The controller entries look like this
def index
#posts = Post.all(:order => 'created_at DESC')
end
or
def posts
#posts = Post.all(:conditions => {'user_id' => params[:id]}, :order => 'created_at DESC')
end
and the partials are
<%= render :partial => #posts %>
In each view is a _posts.html.erb file, and each is slightly different
home/_posts.html.erb looks like this
<%= div_for post do %>
Posted <%= time_ago_in_words(post.created_at) %> ago
Posted By <%= post.user_id %>
<%= post.text %>
<% end %>
while posts/_post.html.erb looks like this
<%= div_for post do %>
Posted By <%= post.user_id %>
<%= post.text %>
<% if post.created_at > 52.hours.since %>
<%= distance_of_time_in_words_to_now(post.created_at) %>
<% else %>
<%= post.created_at.strftime("%c") %>
<% end %>
<% end %>
Now the strange part is that on all the pages index.html.erb, users/show.html.erb, posts/index.html.erb, the partial that is being displayed is the posts/_post.html.erb. The others are being completely ignored.
my understanding was that render :partial would take the #posts and render _posts.html.erb from the current view. But this isn't happening, as only the posts/_post.html.erb is being rendered from all views.
I've looked in the routes.rb file, but don't have anything in there that would cause this problem.
Can anybody tell me why I am not displaying the proper partials?
-----------Edited --------------------------------
The directory structure for views is as follows
views
- home
-_post.html.erb
-index.htlm.erb
- layouts
- posts
-_post.html.erb
-index.html.erb
-posts.html.erb
- sessions
- users
-_post.html.erb
-new.html.erb
-show.html.erb
I hope that helps.
"post", :collection => #posts%>
maybe rails automatically defines path to the partial when you pass only collection
You're passing the collection as the argument that rails is expecting to be the name of the partial. Your call to render should look like this
<%= render partial: "post", collection: #posts %>
This will render app/views/posts/_post.html.erb, passing the local variable post to the partial.
Additionally, (is sometimes handy) there's an iteration object that is made available to this view, partial_name_iteration, that has information about the total size of the #posts collection, and the index of the current object.