Ajax page.replace_html problems with partials in Rails - ruby-on-rails

I am having a problem with a pretty simple AJAX call in rails. I have a blog-style application and each post has a "like" feature. I want to be able to increment the "like" on each post in the index using AJAX onclick. I got it to work; however, the DOM is a bit tricky here, because no matter what partial its looking at, it will only update the TOP partial. so if I click "like" on post #2, it will update and replace the "likes" on post #1 instead.
Code for _post partial:
<some code here...>
<div id="postcontent">
Posted <%= post.created_at.strftime("%A, %b %d")%> <br />
</div>
<div id="postlikes">
<%= link_to_remote 'Like', :url => {:controller => 'posts', :action => 'like_post', :id => post.id}%>
<%= post.like %>
</div>
code for _postlikes partial:
<div id="postlikes">
<%= link_to_remote 'Like', :url => {:controller => 'posts', :action => 'like_post', :id => #post.id}%>
<%= #post.like %>
</div>
</div>
like_post.rjs code:
page.replace_html "postlikes", :partial => "postlikes", :object => #post
page.visual_effect :highlight, "postlikes", :duration => 3
So this all works properly for the first "postcontent" div. But this is an index of posts, so if I wanted to updated the second "postcontent" div on the page, it will still replace the html of the first.
I understand the problem, I just don't know how to fix it :)
Thanks in advance!

Change your
<div id="postlikes">
to
<div id="postlikes_<%= post.id %>">
And then,
page.replace_html "postlikes_#{#post.id}", :partial => "postlikes", :object => #post

It's because your Div ID is the same for each partial. You need to do something like this:
<div id="<%= dom_id(post) %>">
and
<div id="postlike_<%= dom_id(post) %>">
I'm not too sure how you're setting this up but you need to have unique ids for each post (and potentially post-likes).
J

Related

How to ajax reload partial from partials

I have an app in which I different networks have messages.
In my network show view I display all the messages in with a partial "overview" which shows a link to the message content. The content of the messages is loaded with ajax inside #detailed div:
<div class="span2" id="sidebar">
<%= render :partial => 'shared/sidebar' %>
</div>
<div class="span4" id="overview">
<%= render :partial => 'overview' %>
</div>
<div class="span6" id="detailed">
<%= render :partial => 'nothing' %>
</div>
_overview.html.erb, in which i :
<h2>Messages</h2>
UNREAD:
<%= render :partial => 'items', :collection => #task.find_all{|item| item.unread == true }.sort_by(&:created_at).reverse, :as => :item %>
READ:
<%= render :partial => 'items', :collection => #task.find_all{|item| item.unread == false }.sort_by(&:created_at).reverse, :as => :item %>
_items.html.erb:
<%= div_for item do %>
<%= link_to(network_message_path(#network, item), :remote => true, :class => ["message item", ("unread" if item.unread == true)]) do %>...<% end %>
<% end %>
The message is contains a partial again with the full content, comments etc.. Code by which the message is loaded:
$("#detailed").hide().html("<%= j(render('show_message', :message => #message)) %>").fadeIn('fast');
If someone opens the detailed view, I update the unread status of the message to false. I would like to reload the overview partial, if someone loads the message into the details. One solution would be to just use jQuery to move things around, but the system will become more complicated with more filtering options. Therefor, reloading the overview partial would be a simpler solution. But what would be the fastes way to do so? As I need to reload the show method in the networks controller, alongside loading the show method in the message controller.
What would be the best solution, besides jQuery?
Created a module to load the overview partial with ajax.

Rails 3: Can't add correct route to legacy code

Believe you can help me.
I'm trying to add new functionality to legacy code (Typo). But it seems that there is some problem about routing.
In the project routes are generated the following way:
%w{advanced cache categories comments content profiles feedback general pages
resources sidebar textfilters themes trackbacks users settings tags redirects seo post_types }.each do |i|
match "/admin/#{i}", :to => "admin/#{i}#index", :format => false
match "/admin/#{i}(/:action(/:id))", :to => "admin/#{i}", :action => nil, :id => nil, :format => false
end
My functionality is about merging articles. For that I've added new action in the /admin/content controller:
def merge
#some code here
end
A piece of a view partial (_form.html.erb) added by me:
<% if current_user.admin? and !#article.id.nil?%>
<div class=''>
<h4><%= _("Merge Articles") %></h4>
<%= label_tag :merge_with, 'Article ID' %><%= text_field_tag :merge_with, nil, :size => 20 %>
<%= button_to 'Merge', admin_content_merge_path(:id => #article.id) %>
</div>
<%end%>
This partial is rendered by another partial (_edit.html.erb)
<%= form_tag(form_action, :id => "#{form_type}_form", :enctype => "multipart/form-data", :class => className) do %>
<%= render :partial => "form" %>
<% end %>
And finally _edit.html.erb is rendered by view new.html.erb
<%= render "admin/shared/edit", { :form_type => "article", :form_action => { :action => "new", :id => #article.id , :class => ('autosave')} } %>
The problem is how to write a correct route for the controller action above which will allow me to render an edit page containing newly merged article. I wrote:
match "/admin/content/merge/:id" => "admin/content#merge",:as => 'admin/content/merge'
rake routes output:
admin_content_merge /admin/content/merge/:id(.:format) {:controller=>"admin/content", :action=>"merge"}
But the new or edit action is being invoked as I can see.
Apparently, my route is wrong, isn't it?
Could you please help me with this.
Thanks in advance!
Update
Up-to-date new.html.erb:
<% #page_heading = _('New article') %>
<%= render "admin/shared/edit", { :form_type => "article", :form_action => { :action => "new", :id => #article.id , :class => ('autosave')} } %>
<% if current_user.admin? and !#article.id.nil?%>
<%= form_tag "/admin/content/merge/#{#article.id}" do %>
<h4><%= _("Merge Articles") %></h4>
<%= label_tag :merge_with, 'Article ID' %>:
<%= text_field_tag :merge_with %><br />
<%= submit_tag "Merge" %>
<% end %>
<% end %>
Read the hint from the course:
HINT:Nesting is invalid in HTML.
That means that you can't nest form tags, don't put the form tag in another form tag, your nested form wont be able to do a correct action.
Since you have to put your code at the end of the page, try and see how to do it with having your merging form tag below the main edit article form tag. So basically you can find where the big form tag ends and put it below it.
Try to see if you can figure it out, and if not, don't hesitate to ask :)
Btw. I think everybody had some problem with this

Rails 3 - button_to update same page with controller#method

In my project I have the following form_tag to select a Site
<%= form_tag({:controller => "hvacs", :action => "index"}, :method => "get") do %>
<div class="field">
<%= select :p, :site_sel, #user_sites.map{|s| [s.name, s.id]} %>
</div>
<div class="actions">
<%= submit_tag("Select site") %>
</div>
<% end %>
This form_tag updates the index page through calling its method in the controller again.
I have the following button_to
<td><%= button_to 'Select', {:controller => "hvacs", :action => "select"}, :method => "get" %></td>
I would like to achieve a similar update with this as above rather than redirect to a new page with "select_path" etc, but the above does not seem to work.
How can I achieve this? Cheers!
OK, this looked so much like my AJAX problem, I tried to make it one!
I think all you need is a simple render statement in your select action
render :index
or
render :action => 'index'
But see http://guides.rubyonrails.org/layouts_and_rendering.html#using-redirect_to for more.
The following solution worked. Apologies if I was not so clear on what I was looking for.
<%= button_to 'Select', review_hvacs_path(:h => hvac, :a => params[:a], :s => params[:s]) %>
I was trying to pass parameters with the button, while staying on the review page.

RoR: Replace_html with partial and collection not functioning

I am trying to create a tabbed interface using the prototype helper method "replace_html." I have three different partials I am working with. The first one is the 'main tab' and it is loaded automatically like so:
<div id = "grid">
<% things_today = things.find_things_today %>
<%= render :partial => "/todaything", :collection => things_today, :as =>:thing %>
</div>
...which works fine. Similarly, I have a _tomorrowthing partial which would replace the content in the 'grid' div like so:
<%things_tomorrow = things.find_things_tomorrow%>
<%= link_to_function('Tomorrow',nil, :id=>'tab') do |page|
page.replace_html 'grid' , :partial => '/tomorrowthing',:collection => things_tomorrow, :as => :thing
end %>
If I click on this tab nothing happens at all. Using firebug, the only errors I find are a missing ) after argument list which is contained in the Element.update block where the link_to_function is called. What am I doing wrong?
Hey Jack i try to reproduce the same but i can't i never used link_to_function before but
Following code may help to achieve the same you want
<%= link_to_remote "Today Thing", :url=>{:action=>"things", :id=>'today'}%>
<%= link_to_remote "Tomorrow Thing", :url=>{:action=>"things", :id=>'tomorrow'}%>
<div id = "grid">
<% #things = things.find_things_today %>
<%= render :partial => "/todaything", :collection => #things %>
</div>
in controller
def things
#things= (params[:id]=="today")? things.find_things_today : things.find_things_tomorrow
render :update do |page|
page.replace_html 'grid', :partial => (params[:id]=="today")? "/todaything" : '/tomorrowthing' , :objects=> #things
end

Ajax form not showing up with ruby on rails form_remote_tag

This is all new territory for me, but I am working through a Rails book that was written before start_form_tag was deprecated and I am running into problems with the books example code using remote_form_tag. I have the other forms working but can't get this one up and running. Here's the code:
<h1>Categories</h1>
<ul id="category_list">
<%= render :partial => 'category', :collection => #categories %>
</ul>
<br/>
<p id="add_link"><%= link_to_function("Add a category", "Element.remove('add_link');
Element.show('add_category')") %></p>
<div id="add_category" style="display:none;">
<%= form_remote_tag(:url => {:action => 'new'},
:update => "category_list",
:position => :bottom,
:html => {:id => 'category_form'}) %>
Name: <%= text_field "category", "name" %>
<%= submit_tag 'Add' %>
<%= end_form_tag %>
</div>
This is exactly how it appears in the book, and doesn't compile. I've tried changing to match the form_tag blocks but the form enclosed by the "add_category" div never shows up.
Thanks!
UPDATE: Just found that it doesn't appear that the prototype script is not getting loaded.
both the remove and show methods on Element are showing up as undefined in Firebug. I am not sure why it is not showing up though.
I left out the = sign when including the javascript libraries in standard.html
Line should be this:
<%= javascript_include_tag :defaults %>
Vote to close this question?

Resources