userden
userden

Reputation: 1683

Rails 4: Toggle link_to with Ajax and jQuery (nested resources)

I have 'complete' and 'incomplete' links on 'ideas'. I would like to toggle them without page reload.

Here is my current code:

_idea.html.erb partial:

<li id="<%= dom_id(idea) %>">
    <%= idea.description %>
    <% if idea.completed? %>
           <%= link_to "Incomplete", complete_project_idea_path(idea.project, idea), method: :patch, remote: true %>
      <% else %>
           <%= link_to "Complete", complete_project_idea_path(idea.project, idea), method: :patch, remote: true %>
      <% end %>
 </li>  

Here is my controller action (I'm using nested resources):

def complete
  @project = Project.find(params[:project_id])
  @idea = @project.ideas.find(params[:id])
    respond_to do |format|
     @idea.toggle_completion!
         format.html {redirect_to root_path}
         format.js { }
    end
end

And in the idea.rb model:

def completed?
   !completed_at.blank?
end

def toggle_completion!
    if completed?
         update_attribute(:completed_at, nil)
    else
         update_attribute(:completed_at, Time.now)
    end
end

Complete.js.erb file;

$('#<%= dom_id(@idea)%>').html("What here? How can I toggle between the complete and incomplete links?");

I also tried putting the link_to in new partials, but that became too complicated (because they were sub partials) and didn't work either.

What should I try in my complete.js.erb file?

EDIT: Thank you @Fer! I did the following changes, however it doesn't fully work yet.

I changed the complete.js.erb to:

$("#toggle_completion_link").text("<%= @idea.completed? ? 'Incomplete' : 'Complete' %>")

I changed the idea to @idea, because without it I got an 'undefined local variable or method `idea'' error.

Also in the _idea.html.erb partial, which is under projects/idea.html.erb, I changed to:

 <%= link_to (idea.completed? ? 'Incomplete' : 'Complete'), complete_project_idea_path(idea.project, idea), method: :patch, remote: true, id: 'toggle_completion_link' %>

But it's not working properly yet, though I do get a 'completed 200 ok' message.

Started PATCH "/projects/1/ideas/4/complete" for ...
Processing by IdeasController#complete as JS
Parameters: {"project_id"=>"1", "id"=>"4"}
User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1  ORDER BY "users"."id" ASC LIMIT 1  [["id", 1]]
Project Load (0.2ms)  SELECT  "projects".* FROM "projects" WHERE "projects"."id" = $1 LIMIT 1  [["id", 1]]
Idea Load (0.2ms)  SELECT  "ideas".* FROM "ideas" WHERE "ideas"."project_id" = $1 AND "ideas"."id" = $2  ORDER BY priority ASC  LIMIT 1  [["project_id", 1], ["id", 4]]
Rendered ideas/complete.js.erb (0.5ms)
Completed 200 OK in 9ms (Views: 3.3ms | ActiveRecord: 1.8ms)

Upvotes: 1

Views: 853

Answers (1)

Fer
Fer

Reputation: 3347

Well, in your case you just need to change the link text, as both links point to the same url and method.

I would DRY it a little like following in _idea.html.erb

<li id="<%= dom_id(idea) %>">
    <%= idea.description %>
    <%= link_to (idea.completed? ? 'Incomplete' : 'Complete'), complete_project_idea_path(idea.project, idea), method: :patch, remote: true, id: 'toggle_completion_link' %>
 </li>

Note the id attribute for the link in the end.

If you are displaying more than one project and you have id issues, I would use the dom_id(idea) as the id for the link (or some variation like dom_id(idea) + '_link'), and not for the li containing it.

And then, as answer from your ajax request, in your complete.js.erb file:

$("#toggle_completion_link").text("<%= idea.completed? ? 'Incomplete' : 'Complete' %>")

You could also replace the whole thing, but I don't see the point here because you just need to toggle the link text. Anyway for didactics you could render the whole partial like following:

$("#<%= dom_id(idea) %>").replace("<%= escape_javascript(render 'idea', object: @idea %>")

You might need to adjust the partial path, as you don't say where it is located

Upvotes: 1

Related Questions