Rails 4 / jQuery:需要在表单输入中输入值以自动填充其他输入

Posted

技术标签:

【中文标题】Rails 4 / jQuery:需要在表单输入中输入值以自动填充其他输入【英文标题】:Rails 4 / jQuery: Need entry of value in a form input to autofill other inputs 【发布时间】:2016-05-24 05:18:31 【问题描述】:

使用 simple_form,我试图获取一个 id 输入 (team_id) 的条目,以在创建新 team_game 的表单中自动填充几个其他输入(team_cityteam_name)。我已经完成了我能找到的所有实现,但无济于事(我最近的参考资料:Jquery ajax and controller method)。这对我来说就像流沙,越挣扎,越被推倒。我的代码如下。目前,它在 javascript 中抛出 AJAX 错误。我也在控制台中得到这个:

Started GET "/team_games/populate_team_city_and_name?team_id=1" for ::1 at 2016-02-12 13:28:50 -0800
Processing by TeamGamesController#show as JSON
  Parameters: "team_id"=>"1", "id"=>"populate_team_city_and_name"
  TeamGame Load (0.3ms)  SELECT  "team_games".* FROM "team_games" WHERE "team_games"."id" = $1 LIMIT 1  [["id", 0]]
Completed 404 Not Found in 2ms (ActiveRecord: 0.3ms)

ActiveRecord::RecordNotFound - Couldn't find TeamGame with 'id'=populate_team_city_and_name:

所以,除了我的 AJAX 问题之外,我的路由似乎做错了什么(以此为指导:How to add a custom action to the controller in Rails 3)。

使用 Ruby 2.3.0 和 Rails 4.2.5。任何帮助将不胜感激。

models/team_game.rb
class TeamGame < ActiveRecord::Base

  attr_accessor :team_city
  attr_accessor :team_name
  attr_accessor :opposing_team_city
  attr_accessor :opposing_team_name

  belongs_to :team, class_name:  'Team',
                    inverse_of:  :team_games

end
models/team.rb
class Team < ActiveRecord::Base

  has_many :team_games, class_name:  'TeamGame',
                        inverse_of:  :team

end
查看/team_games/_form.html.haml
= simple_form_for @team_game do |f|

  = f.input :team_id,   input_html:  id: 'team-id' 
  = f.input :team_city, input_html:  id: 'team-city' 
  = f.input :team_name, input_html:  id: 'team-name' 
controllers/team_games_controller.rb
def populate_team_city_and_name(team_id)

  @team = Team.where(id: team_id)

  respond_to do |format|
    format.json  render json: @team 
  end

end


private

def team_game_params
  params.require(:team_game).
    permit(:team_id,
           :team_city,
           :team_name,
           :is_home_team,
           :opposing_team_id,
           :opposing_team_city,
           :opposing_team_name,
           :stadium_name
           :game_date,
           :game_time)
end
assets/javascripts/team_games.js
$(document).ready(function() 

  $('#team-id').change(function(e) 
    e.preventDefault();

    var teamId = $('#team-id').val();

    request = void 0;
    request = $.ajax(
      url: 'populate_team_city_and_name',
      type: 'GET',
      dataType: 'json',
      data:  team_id: teamId 
    );

    request.done(function(data, textStatus, jqXHR) 
      if (data.length > 0) 
        $('#team-city').val(data.city);
        $('#team-name').val(data.name);
       else 
        $('#team-name').val('There is no team with entered Id');
      
      console.log("Success!!")
    );

    request.error(function(jqXHR, textStatus, errorThrown) 
      console.log("AJAX Error: #textStatus");
    );

  );
);
config/routes.rb
resources :team_games do
  member do
    get :populate_team_city_and_name
  end
end

更新:工作中

以下是我为使自动填充正常工作所做的更改。它们可能并非都是必需的,但它确实有效,所以就是这样。感谢 Jeff F. 带领我走上正确的道路。

view/team_games/_form.html.haml(已修改)
= simple_form_for @team_game do |f|

  = f.input :team_id,   input_html:  id: 'team-id' 
  #no-team-with-id-msg There is no team with entered id
  = f.input :team_city, input_html:  id: 'team-city' 
  = f.input :team_name, input_html:  id: 'team-name' 
controllers/team_games_controller.rb(修订)
def populate_team_city_and_name

  @team = Team.where(id: params[:team_id])

  respond_to do |format|
    format.json  render json: @team 
  end

end


private

def team_game_params
  params.require(:team_game).
    permit(:team_id,
           :team_city,
           :team_name,
           :is_home_team,
           :opposing_team_id,
           :opposing_team_city,
           :opposing_team_name,
           :stadium_name
           :game_date,
           :game_time)
end
assets/javascripts/team_games.js(已修改)
$(document).ready(function() 

  $("#no-team-with-id-msg").hide();

  $('#team-id').change(function(e) 

    e.preventDefault();
    var teamId = $('#team-id').val();

    request = void 0;
    request = $.ajax(
      url: '/team_games/populate_team_city_and_name?team_id=' + teamId,
      type: 'GET',
      dataType: 'json'
    );

    request.done(function(data, textStatus, jqXHR) 
      if (data.length > 0) 
        $("#no-team-with-id-msg").hide();
        $('#team-city').val(data[0].city);
        $('#team-name').val(data[0].name);
       else 
        $("#no-team-with-id-msg").show();
        $('#team-city').val('');
        $('#team-name').val('');
      
    );

    request.error(function(jqXHR, textStatus, errorThrown) 
      console.log("AJAX Error: #textStatus");
    );

  );
);
config/routes.rb(已修改)
get 'team_games/populate_team_city_and_name',
  to: 'team_games#populate_team_city_and_name',
  as: 'populate_team_city_and_name',
  defaults:  format: 'json' 

resources  :team_games
resources  :teams

我的部分路由问题似乎是我之前在资源路由之后有“get”路由,我猜这就是为什么 javascript 'GET' 路由到 team_games#show 操作。

我还更改了消息 “没有输入 id 的团队” 消息的处理,因为它似乎不适合出现在输入中。

【问题讨论】:

【参考方案1】:

您错误地使用了该路由的 url。尝试将您的 ajax 更改为:

request = $.ajax(
  url: 'team_games/' + teamId + '/populate_team_city_and_name',
  type: 'GET',
  dataType: 'json'
);

然后在你的控制器中:

@team = Team.where(id: params[:id])

【讨论】:

感谢您的回复,杰夫!如果我做出你建议的改变,首先我得到: Started GET "/team_games/team_games/1/populate_team_city_and_name" for ::1 at 2016-02-12 15:22:48 -0800 ActionController::RoutingError (No route matches [GET] "/team_games/team_games/1/populate_team_city_and_name"): 所以,路由仍然有些奇怪(它在 URL 中增加了一倍 /team_games。) 如果我在开头添加一个“/”,它似乎会生成正确的路线,但后来我得到这个:Started GET "/team_games/1/populate_team_city_and_name" for ::1 at 2016-02-12 15:27:44 -0800 Processing by TeamGamesController#populate_team_city_and_name as JSON Parameters: "id"=&gt;"1" Completed 500 Internal Server Error in 0ms (ActiveRecord: 0.0ms) ArgumentError - wrong number of arguments (given 0, expected 1):teamId 在中间时,它似乎正在通过它就像显示或编辑一样的“id”,而不是控制器方法的“team_id”。 我对此进行了编辑,但答案对于编辑来说有点遥远,所以我提出了一个新的答案。不过,+1 是因为走在正确的轨道上。【参考方案2】:

我对上面的答案进行了一些编辑,但实际上离正确有点太远了,所以我重新回答了。不过,由于它走在正确的轨道上,因此受到了赞成。

在表单中添加一行,例如:

= simple_form_for @team_game do |f|
  = f.input :id, as: hidden, :input_html =>  id: 'team-game-id', :value => @team_game.id 
  = f.input :team_id,   input_html:  id: 'team-id' 
  = f.input :team_city, input_html:  id: 'team-city' 
  = f.input :team_name, input_html:  id: 'team-name' 

然后在你的 JS 中:

var teamId = $('#team-id').val();
var teamGameId = $("#team-game-id").val();

 ... 

request = $.ajax(
  url: '/team_games/' + teamGameId + '/populate_team_city_and_name?team_id=' + teamId,
  type: 'GET'
);

查询参数的原因是因为您无法在 URL 中指定 teamId,除非您创建允许您这样做的路由。成员资格是 TeamGame 模型,而不是团队。或者,您可以指定如下路线:

get '/team_games/:id/populate_team_city_and_name/:team_id' => 'team_games#populate_team_city_and_name'

但按原样,您没有匹配的路线。但是查询参数会显示在params中。

然后在你的控制器中:

@team = Team.find params[:team_id]

您可能还想确保该 Team 不仅存在,而且 Team.team_games 包含有问题的 TeamGame。但我会把这个练习留给你!

【讨论】:

感谢您的出色回应。当你把它放在一起的时候,我仍然在追寻杰夫的领先优势,正如你所说,这让我走上了正确的轨道。我最终想出了一个与您不同的解决方案,但也许不是更好。如果您不介意查看我对原始问题的编辑并告诉我您是否发现任何陷阱,我将不胜感激。谢谢! 在创建新的team_game 时,我的似乎可以正常工作,但我需要合并您所做的以编辑现有的,例如你使用了@team_game.id,当我创建一个新的team_game 时它还不存在,但在我编辑它时是必要的。 我觉得没问题。我唯一的建议是使用team#show/team_games/populate_team_city_and_name 调用移至TeamsController。然后,如果您向其传递一个寻找application/json 的接受标头,您应该能够获得 JSON。但那是我是一个坚持不懈的人,并不影响它最终的工作方式。

以上是关于Rails 4 / jQuery:需要在表单输入中输入值以自动填充其他输入的主要内容,如果未能解决你的问题,请参考以下文章

在提交失败时保持 jQuery - Rails

Rails 5:jquery用户输入数据不保存

Rails 4 真实性令牌 - 在标题和表单隐藏输入中?

Rails 表单,如何使用 jquery 设置隐藏字段的值

Rails 6将输入添加到页面中的列表

如何从rails中的视图将值传递给jquery?