Reputation: 479
I need some guidance on how to update a div on a page with Jquery/Ajax without actually loading the page. Before I ask the question, I will provide some necessary information.
I have two models:
Scoreboard
Model (has_many :teams
)Team
Model (belongs_to scoreboard
)On scoreboard#show
page, I have rendered a partial to display all @scoreboard.teams
.
The partial displays all the teams in seperate divs as detailed in the following code:
<div class ="team-list" id="team_<%=team.id%>">
<div class= "boxin1"><%= team.name %></div>
<div class= "boxin2"><%= team.win %></div>
<div class= "boxin2"><%= team.loss %></div>
<div class= "boxin2"><%= team.tie %></div>
<span class= "boxin3 btn btn-primary"><%= link_to "Edit", edit_scoreboard_team_path(@scoreboard, team), remote: true %> </span>
<span class= "boxin3 btn btn-primary"><%= link_to "Del", [@scoreboard, team], remote: true, method: :delete, data: { confirm: "Are you sure you want to delete the team?" } %>
</div>
Now my questions concerns the Edit button which on click, calls for an ajax request which, brings up a form to edit a team, and then the form, on submission, calls for the update method in the Teams Controller. For further clarification, here is the relevant code:
Team Controller methods for edit and update:
def edit
@scoreboard = Scoreboard.find(params[:scoreboard_id])
@team = @scoreboard.teams.find(params[:id])
respond_to do |format|
format.html {redirect_to scoreboard_url(@team.scoreboard_id)}
format.js
end
end
def update
@scoreboard = Scoreboard.find(params[:scoreboard_id])
@team = @scoreboard.teams.find(params[:id])
if @team.update_attributes(team_params)
respond_to do |format|
format.html {redirect_to scoreboard_url(@team.scoreboard_id)}
format.js
end
else
render 'edit'
end
end
Here is the code for the edit.js.erb and update.js.erb files and description to clarify what is happening in them:
edit.js.erb
$("#team_<%[email protected]%>").hide();
$("#team_<%[email protected]%>").after("<%= j render 'teamedit'%>");
So upon clicking the edit_path link button, the div for team being edited is hidden, and a teamedit form is rendered right after it.
update.js.erb
$("#edit_team_<%[email protected]%>").hide();
$("#team_<%[email protected]%>").load("scoreboards/show.html.erb"); #help needed here
$("#team_<%[email protected]%>").show();
Now when the update controller method is called after form submission, the form is hidden with jquery, and I want to reload the team div that I hid earlier, and then show it with its updated values.
I felt like the .load() jquery method would be relevant in refreshing that div with the new edited values however it is not working. In conclusion, edit.js.erb works fine but update.js.erb does not work due to the 2nd line in the code. The div is not being refreshed with updated values. Could anyone offer some guidance on a different method or let me know what I'm doing wrong?
Edit:
Another item of relevance. Team_Params method In Teams controllers:
private
def team_params
params.require(:team).permit(:name, :win, :loss, :tie)
end
Upvotes: 4
Views: 3918
Reputation: 2927
Are you sure that your update method is working? I would check that first. You need to include scoreboard_id in your team_params method.
Upvotes: 0
Reputation: 76774
ERB
Furthering dimakura
's answer, it seems you need some help with the understanding of the js erb
infrastructure:
Notice the format.js in the respond_to block; that allows the controller to respond to your Ajax request. You then have a corresponding app/views/users/create.js.erb view file that generates the actual JavaScript code that will be sent and executed on the client side.
Contrary to the standard asset-pipeline, controller-generated JS.erb
allows you to invoke ERB
functionality with any instance variables set in your controller.
As such, your question of how to "load" another ERB view into your JS can be handled using the render method in ERB:
#app/views/teams/update.js.erv
$("#team_<%=j @team.id %>").replacewith('<%=j render("scoreboards/show") %>');
The target view is up to you. Seems dimakura
used a partial, it's up to you which one you go with.
--
Process
In regards your comments about processing the new data, you have to understand that in js.erb
, you'll have access to the same data that you'd have in any other controller action.
This means that if you're not receiving the most up-to-date data, it's a systemic problem.
I would do the following:
#app/controllers/teams_controller.rb
class Teamscontroller < ApplicationController
before_action :set_vars
def edit
respond_to do |format|
format.html {redirect_to @scoreboard }
format.js
end
end
def update
respond_to do |format|
if @team.update team_params
format.html { redirect_to @scoreboard }
format.js
else
format.html { render :edit }
end
end
private
def set_vars
@scoreboard = Scoreboard.find params[:scoreboard_id]
@team = @scoreboard.teams.find params[:id]
end
def team_params
params.require(:team).permit(:name, :win, :loss, :tie)
end
end
If this doesn't work, it generally means you've got a problem with your update process (IE update
won't be working properly).
Upvotes: 0
Reputation: 7655
You almost done everything.
The only remaining part is to put team information into a partial, named e.g. _team.html.erb
:
<div class ="team-list" id="team_<%=team.id%>">
<div class= "boxin1"><%= team.name %></div>
<div class= "boxin2"><%= team.win %></div>
<div class= "boxin2"><%= team.loss %></div>
<div class= "boxin2"><%= team.tie %></div>
<span class= "boxin3 btn btn-primary"><%= link_to "Edit", edit_scoreboard_team_path(@scoreboard, team), remote: true %> </span>
<span class= "boxin3 btn btn-primary"><%= link_to "Del", [@scoreboard, team], remote: true, method: :delete, data: { confirm: "Are you sure you want to delete the team?" } %>
</div>
and then update.js.erb
:
$("#edit_team_<%[email protected]%>").hide();
$("#team_<%[email protected]%>").load("<%= j render partial: 'team', locals: {team: @team} %>");
$("#team_<%[email protected]%>").show();
Upvotes: 6