Rails-从表单选择下拉列表中向控制器传递参数

时间:2018-08-22 00:14:21

标签: javascript ruby-on-rails ajax

我有2个模型:TeamQuest。创建新团队时,我会下拉所有任务。选择任务后,我要显示有关该任务的信息。

我的理解是,表单中的所有内容都在客户端,并且需要AJAX才能将所选任务传递到服务器端。我的代码基于this堆栈溢出答案。

这是我构造表单的方式:

app / views / teams_form.html.erb

<%= form_for(@team) do |f| %>
  <fieldset>
    <ol>
      <li>
        <%= f.label :name %>
        <%= f.text_field :name %>
      </li>
      <li>
        <%= f.label :quest_id %>
        <%= f.select :quest_id, 
                     options_from_collection_for_select(@quests, :id, :name), 
                     {}, {remote: true, url: '/teams/new', method: 'get'} %>
      </li>
      <% if @x != nil && @x.id != nil %>
        <li><%= @x.id %></li>
      <% end %>
    </ol>
    <p>
      <%= f.submit %>
    </p>
  </fieldset>
<% end %>

app / controllers / team_controller.rb

def new
  @team = Team.new
  @quests = Quest.all
  respond_to do |format|
    if params[:quest_id] != nil
      @x = Quest.find(params[:quest_id])
    end
    format.html #new.html.erb
    format.json
    format.js
  end
end

我的目标是将:quest_id参数从表单传递到@x变量,并在表单中使用它。

这什么也没产生。我没有在控制器中获取参数,也不确定我缺少什么。

3 个答案:

答案 0 :(得分:0)

根据共享的描述,您似乎无法从下拉列表中获取所选项目的值。

下面提到的代码用于从下拉列表中选择值,您也可以使用浏览器的开发人员工具检查该值。

quest = $("#quest_id").val();

注意:假设选择器ID为quest_id,请根据您的表单进行更改。

现在,您可以使用下面提到的代码来调用ajax。

$.ajax({
  type: "GET",
  url: "/teams/new",
  data:{ quest_id: quest },
  dataType: "json",
  success:function(data){
    # logic for using ajax result
  }

希望有帮助!

答案 1 :(得分:0)

最后成功了,想发表,如果有人看到并且遇到相同的问题:

我被提出了一个单独的AJAX请求

app / views / teams_form.html.erb

<script>
   $(document).ready(function() {
    $('#team_quest_id').change(function() {
       $.ajax({
         url: "/teams/new",
         data: {quest_id: $("#team_quest_id option:selected").val()},
         dataType: "script",
         method: "get",
         success: function(r){}
       });
     });
   });
</script>

我移动了参数分配的位置

app / controllers / team_controller.rb

def new
  @team = Team.new
  @quests = Quest.all
  if params[:quest_id] != nil
    @x = Quest.find(params[:quest_id])
  end
  respond_to do |format|
    format.html #new.html.erb
    format.json
    format.js
  end
end

最重要的是-我创建了一个js文件来呈现我的表单

app / views / new.js.erb

$('#new_team').html("<%= j (render 'form') %>");

This video很有帮助

答案 2 :(得分:0)

您问题中的代码几乎是正确的,您忘记了将属性嵌套在 data 中。

<% # app/views/teams_form.html.erb %>

<%= f.select :quest_id, 
                     options_from_collection_for_select(@quests, :id, :name), 
                     {}, {remote: true, url: '/teams/new', method: 'get'} %>
<% # should be: %>
<%= f.select :quest_id, 
                     options_from_collection_for_select(@quests, :id, :name), 
                     {}, {data: {remote: true, url: '/teams/new', method: 'get'}} %>
<% # or even better, use the path helper instead of the hard coded path %>
<%= f.select :quest_id, 
                     options_from_collection_for_select(@quests, :id, :name), 
                     {}, {data: {remote: true, url: new_team_path, method: :get}} %>

正确设置属性后,我们仍然需要进一步修复表单。在请求页面时,浏览器将请求该表单,但是将永远不会设置@x。由于不会将ERB发送给客户端,因此我们需要添加一个句柄以找到我们的任务容器元素。

<% # app/views/teams_form.html.erb %>

<% if @x != nil && @x.id != nil %>
  <li><%= @x.id %></li>
<% end %>
<% # should be something like %>
<li id="quest-info-container"></li>

现在将控制器中的HTML请求与JS请求分开。

# app/controllers/teams_controller.rb

def new
  respond_to do |format|
    format.html do
      @team = Team.new
      @quests = Quest.all
    end
    format.js do
      @quest = Quest.find(params.dig(:team, :quest_id))
    end
  end
end

您可以通过将选择数据路径发送到另一个用于处理任务预览的网址来简化上述操作。

现在,我们需要在容器中渲染预览,为此,我们需要2个文件,首先是结果结构的外观。请记住,它将在容器内呈现。

<% # app/views/teams/_quest_preview.html.erb %>

<% # Here comes what you want to display about the quest. You can give this %>
<% # file another name if you like. You have @quest to your disposal here. %>
<%= @quest.id %> <strong><%= @quest.name %></strong>

现在,我们只需要一个JavaScript文件即可将上述结构加载到我们创建的句柄中。

<% # app/views/teams/new.js.erb %>

handle = document.getElementById('quest-info-container');
handle.innerHTML = '<%= j render('quest_preview') %>';

jescape_javascript的别名。如果局部文件不在同一目录中,请使用<%= j render('other_dir/some_partial') %>