Rails check_box_tag如何在ajax选中时传递值

6
在我的Task模型的索引页面上,我想为每一行显示一个复选框,对应于我的Task数据库表中的布尔字段“complete”。
目前我的代码进入了"Complete"方法,但它不包含用户刚刚执行的复选框的值(即,如果他们刚刚勾选了复选框,则不会将true传递给我的"Complete"方法)。
如何传递用户刚刚执行的值 - 已选或未选?
/views/tasks/index.html.erb
<% @tasks.each_with_index do |task, i| %>
    <tr>
        <td><%= check_box_tag 'Complete', task.complete, task.complete, :data => {:remote => true, :url => url_for( :action => 'complete', :id => task.id, :complete => task.complete ), :method => :put}, :class => 'input-large' %></td>
    </tr>
<% end %>

/controllers/tasks_controller#complete

# PUT /complete/1
  def complete
    @task = Task.find(params[:id])
    p "inside complete"
    p "complete = #{params[:complete]}"
    @task.complete = 

      if @task.update_attributes(params[:task])
        p "inside update"
        render :text => "success" 
      else
        p "inside error"
      end

  end

你需要编写一个onclick事件或onchange事件来发送Ajax调用。我们无法像link_to一样在check_box_tag上发送ajax调用。 - Srikanth Jeeva
请问您能否提供一小段示例代码,展示在您的视图文件和 JavaScript 代码中是如何实现的? - Alex Shmatko
4个回答

9

来自rails/jquery-ujs github仓库的建议对我很有效:https://github.com/rails/jquery-ujs/issues/440#issuecomment-197029277

对于您而言,它应该是:

<%= check_box_tag 'complete', '1', task.complete, {
  onchange: "$(this).data('params', 'complete=' + this.checked)",
  data: { url: url_for(action: 'complete', id: task.id,), remote: true, method: :patch },
} %>

5

如果您正在使用jQuery,您可以编写一个点击事件。

$('.input-large').click(function() {
  var checked; 
  if ($(this).is(':checked')) {
    checked = true;
  } else {
    checked = false;
  } 
  $.ajax({
      type: "POST",
      url: "/tasks/complete",
      data: { id: $(this).data('post-id'), checked: checked }
   });     
});

有没有一种方法可以将响应发送到服务器(已选或未选),而不是使用2个ajax函数? - Catfish
好的,我尝试了你的解决方案,但是出现了错误:“找不到没有ID的任务”。我该如何传递ID? - Catfish
我的复选框元素上没有data-post-id,所以我将check_box_tag的id更改为我的任务id,并将其添加到我的ajax数据中:id: $(this).attr('id') - Catfish

4
从Rails 4开始,您应该能够放弃原始答案中的所有JS。由于jQuery UJS的魔力,您问题中的代码应该可以正常工作。
事实证明,将remote: true添加到输入框会使jquery-ujs以所有好的方式将其变成ajax操作。Thoughtbot的"A Tour of Rails jQuery UJS"简要介绍了这一点(以及其他许多可用的好东西);jQuery UJS wiki中的"Unobtrusive scripting support for jQuery" page也对此进行了彻底的介绍。

2
check_box_tag 'complete', task.complete ? 'false' : 'true', task.complete, ...
:url => url_for( :action => 'complete', :id => task.id )

在您的控制器中,您可以获取params[:complete]。您应该实现complete.js.erb以重新渲染复选框,因此下一次单击将发送反向值。
或者您可以在单击事件上实现js。
$('.input-large').on('click', function() {
  $.ajax({
    type: "PUT",
    url: "/tasks/complete/" + $(this).data('post-id')
    data: { complete: $(this).is(':checked') }
  });
});

不要忘记在复选框中添加data-post-id参数。

如果我选择你的第一个选项,它不会以ajax方式提交。如果我在你的第一个选项中添加:remote => true,它将以ajax方式提交,但是params[:complete]不包含用户刚刚完成的正确值(已选或未选),它只包含数据库中的值。 - Catfish
在你的第二个例子中,我不得不将url更改为$(this).data('url'),因为生成的复选框元素上没有data-post-id。Ajax调用可以工作,但它仍然不包含用户刚刚执行的值(选中或取消选中),而只是继续显示数据库中的值。 - Catfish
在第一个例子中,我使用了...来避免重复项,我在我的环境中复制了它并且它有效。 - Konstantin Ilchenko
1
在第二步中,我写道:“不要忘记将data-post-id参数放置到您的复选框中”。 - Konstantin Ilchenko
我似乎忽略了添加data-post-id参数的部分。不过这很有道理。 - Catfish

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接