[英]Rails Ajax create a new instance of a model and add a checkbox for it to a form
I have a view that renders two form partials: 我有一个呈现两个表单部分的视图:
matches/new.html.erb: matchs / new.html.erb:
<%= render 'players/new' %>
<%= render 'matches/form' %>
matches/form is a form for a new Match. 比赛/表格是新比赛的表格。 On the form you can add existing Players to Teams.
在表单上,您可以将现有玩家添加到团队中。 The Players collection is rendered as a collection of checkboxes.
Players集合呈现为复选框的集合。 When the form is submitted, the Teams get created with those selected Players inside them:
提交表单后,将在团队内部创建选定的玩家:
matches/_form.html.erb: matchs / _form.html.erb:
<%= form_for @match do |f| %>
<%= f.fields_for :team_1 do |team_1_form| %>
<%= team_1_form.label "Team 1" %><br>
<%= team_1_form.collection_check_boxes :player_ids, Player.all, :id, :name, include_hidden: false %>
<% end %>
<br>
<%= f.fields_for :team_2 do |team_2_form| %>
<%= team_2_form.label "Team 2" %><br>
<%= team_2_form.collection_check_boxes :player_ids, Player.all, :id, :name, include_hidden: false %>
<% end %>
<br>
<%= f.submit "Start Match" %>
<% end %>
In players/new you can create new Players: 在玩家/新玩家中,您可以创建新玩家:
players/_new.html.erb: players / _new.html.erb:
<%= form_for @player, remote: true do |f| %>
<%= f.text_field :name %>
<%= f.submit 'Create Player' %>
<% end %>
So the idea is, I want to be able to create a Player (which the form does do successfully, by the way) via AJAX and for that Player's checkbox to be added to the Players' checkbox collection in the view without a page refresh. 因此,我的想法是,我希望能够通过AJAX创建一个Player(顺便说一句,表单确实成功完成了此工作),并且该Player的复选框可以添加到视图中的Player的复选框集合中,而无需刷新页面。
I've tried a few different things (you'll see a few commented-out things in the create.js.erb file). 我尝试了一些其他操作(您会在create.js.erb文件中看到一些注释掉的内容)。 I've been stuck on this for days and I've googled the hell out of it.
我已经坚持了好几天,并且用谷歌搜索了它。 Help please!
请帮助!
Github repo: https://github.com/Yorkshireman/foosball Github仓库: https : //github.com/Yorkshireman/foosball
Controllers: 控制器:
class PlayersController < ApplicationController
def create
@player = Player.create(name: params[:player][:name], league: current_league)
@match = Match.new
current_league.players << @player
respond_to do |format|
format.js {}
end
end
end
class MatchesController < ApplicationController
def new
@player = Player.new
@players = Player.all
@match = Match.new
end
def create
@match = Match.new(league: current_league)
if team_1_player_ids && team_2_player_ids
teams = BuildTeams.call team_1_player_ids, team_2_player_ids, current_league
InsertTeamsIntoMatch.call teams, @match
@match.save
render nothing: true
else
flash[:alert] = "Please select players for both teams"
render :new
end
end
private
def team_1_player_ids
params[:match] && params[:match][:team_1] && params[:match][:team_1][:player_ids]
end
def team_2_player_ids
params[:match] && params[:match][:team_2] && params[:match][:team_2][:player_ids]
end
end
views/players/create.js.erb: 视图/播放器/create.js.erb:
// $("<%= escape_javascript(render partial: 'matches') %>");
// $('#new_match_div').html("<%= escape_javascript(render 'matches/new') %>");
$('#new_match').html("<%= escape_javascript(render 'matches/form') %>");
// $('#new_match').replaceWith("<p>Replaced</p>");
I think there are some inconsistencies between the link to your create_players
branch and the code that you posted in this question. 我认为您
create_players
分支的链接与您在此问题中发布的代码之间存在一些不一致之处。
I checkout out your code at https://github.com/Yorkshireman/foosball/commit/2413eb576f96333acbb02f1bb05689ae1dc47d3e ( temp_branch
), then made the following changes: 我签了你的代码在https://github.com/Yorkshireman/foosball/commit/2413eb576f96333acbb02f1bb05689ae1dc47d3e (
temp_branch
),然后进行了如下修改:
I replaced both @cat
and @dog
with @player
. 我换过两个
@cat
和@dog
与@player
。
I changed the contents of app/views/player/create.js.erb
to read exactly as this: 我将
app/views/player/create.js.erb
的内容更改为完全如下所示:
$("<%= escape_javascript(render @player) %>").appendTo("#new_match"); $('#new_match').html("<p>Replaced</p>"); $('#new_match').html("<%= escape_javascript(render partial: 'matches/form') %>");
The second line has no effect on the end result, so it can be removed. 第二行对最终结果没有影响,因此可以将其删除。
In the PlayersController#create
, I added: 在
PlayersController#create
,我添加了:
@match = Match.new(league: current_league)
Adding a new player successfully updates the checkboxes. 添加新播放器会成功更新复选框。 If those changes do not work for you, then their might a be browser-specific JS problem that you're encountering.
如果这些更改对您不起作用,那么它们可能是您遇到的特定于浏览器的JS问题。
Ok, so this is before any refactoring, but it works. 好的,所以这是任何重构之前的事情,但是可以。
Thanks to sealocal, the create.js now reads: 感谢sealocal,create.js现在显示为:
$("<%= escape_javascript(render @player) %>").appendTo("#new_match");
$('#new_match').html("<%= escape_javascript(render partial: 'matches/form') %>");
But unfortunately, I don't fully understand what is going on here; 但是不幸的是,我不完全了解这里发生了什么。 I thought
appendTo
would actually render the player checkbox in the browser, but it seems the entire partial has be re-rendered on the next line? 我以为
appendTo
实际上会在浏览器中渲染播放器复选框,但似乎整个部分都已在下一行重新渲染了? Why is this? 为什么是这样? What does
appendTo
do exactly? appendTo
到底做什么?
Here's the weird thing - with the PlayersController like this: 这是很奇怪的事情-使用PlayersController是这样的:
class PlayersController < ApplicationController
def create
@player = Player.create(name: params[:player][:name], league: current_league)
@match = Match.new(league: current_league)
current_league.players << @player
respond_to do |format|
format.js {}
end
end
end
I was getting the error: 我收到错误:
Rendered players/create.js.erb (33.7ms)
Completed 500 Internal Server Error in 314ms (ActiveRecord: 19.8ms)
ActionView::Template::Error (Missing partial players/_matches, application/_matches with {:locale=>[:en], :formats=>[:js, :html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]}. Searched in:
* "/home/andrew/projects/foosball/app/views"
So I googled that error code and saw this (not the answer, but where the poster says, on line 3: "it is requesting a view with the same name as the model."). 因此,我搜索了该错误代码,并看到了这个错误代码(不是答案,而是张贴者在第3行上说的:“它正在请求与模型同名的视图。”)。 So I figured this must be some Rails magic, inferring the view from the #create method.
因此,我认为这一定是Rails的魔力,它可以从#create方法推断出视图。 SO... (drum roll)...
等等...
I tried shifting the @match
line to above the @player
line and BOOM! 我尝试将
@match
行移到@player
行和BOOM上方! It worked!: 有效!:
class PlayersController < ApplicationController
def create
@match = Match.new(league: current_league)
@player = Player.create(name: params[:player][:name], league: current_league)
current_league.players << @player
respond_to do |format|
format.js {}
end
end
end
If I'm honest, though, I'm not entirely sure why this works. 不过,如果我说实话,我不完全确定为什么会这样。 For now, I have put it down to Rails, but if someone could shed some more light on it, that would be great.
现在,我将其归结为Rails,但是如果有人可以对其进行更多说明,那就太好了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.