我有一个视图,呈现两个形式的部分:
匹配/ new.html.erb:
<%= render 'players/new' %>
<%= render 'matches/form' %>
matches / form是新Match的表单。在表单上,您可以将现有玩家添加到团队中。 Players集合呈现为一组复选框。提交表单后,将使用其中选定的玩家创建团队:
匹配/ _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 %>
在玩家/新玩家中,您可以创建新的玩家:
播放器/ _new.html.erb:
<%= form_for @player, remote: true do |f| %>
<%= f.text_field :name %>
<%= f.submit 'Create Player' %>
<% end %>
所以我的想法是,我希望能够通过AJAX创建一个播放器(表格确实成功地完成了),然后将该播放器的复选框添加到视图中的播放器复选框集合中,而不是页面刷新。
我尝试了一些不同的东西(你会在create.js.erb文件中看到一些注释掉的东西)。我已经被困在这几天了,我用谷歌搜索了它。求救!
Github回购:https://github.com/Yorkshireman/foosball
控制器:
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
视图/播放器/ 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>");
答案 0 :(得分:1)
我认为您的create_players
分支的链接与您在此问题中发布的代码之间存在一些不一致。
我在https://github.com/Yorkshireman/foosball/commit/2413eb576f96333acbb02f1bb05689ae1dc47d3e(temp_branch
)结帐了您的代码,然后进行了以下更改:
我将@cat
和@dog
替换为@player
。
我将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') %>");
第二行对最终结果没有影响,因此可以将其删除。
在PlayersController#create
中,我补充道:
@match = Match.new(league: current_league)
添加新播放器会成功更新复选框。如果这些更改对您不起作用,那么它们可能是您遇到的特定于浏览器的JS问题。
答案 1 :(得分:0)
好的,所以这是在任何重构之前,但它确实有效。
感谢sealocal,create.js现在显示为:
$("<%= escape_javascript(render @player) %>").appendTo("#new_match");
$('#new_match').html("<%= escape_javascript(render partial: 'matches/form') %>");
但遗憾的是,我并不完全明白这里发生了什么;我认为appendTo
实际上会在浏览器中呈现播放器复选框,但似乎整个部分都在下一行重新渲染?为什么是这样? appendTo
到底做了什么?
这是奇怪的事情 - 像这样的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
我收到了错误:
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"
所以我用Google搜索了错误代码并看到了this(不是答案,但是海报上的说法,在第3行:“它正在请求与模型同名的视图。”)。所以我认为这必须是一些Rails魔术,从#create方法推断出视图。所以......(鼓声)...
我尝试将@match
行转移到@player
行和BOOM之上!它奏效了!:
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
但是,如果我是诚实的,我不会完全确定为什么这样做。现在,我把它归结为Rails,但是如果有人能够对它有更多的了解,那就太棒了。