简体   繁体   English

与Ajax更新的Rails关联表单

[英]Rails association form with Ajax update

I have a model, book, with a has_many association, owns. 我有一个拥有has_many关联的模型,书。 I have it set up where a user can click a button to add the book to their collection. 我设置了它,用户可以单击按钮将书添加到他们的收藏中。 The controller looks as such: 控制器如下所示:

def create
    @book.owns.where(user_id: current_user.id).first_or_create
    @own = Own.where(user_id: current_user.id, book_id: @book.id)
    Own.update(@own, :quantity => "1")
    respond_to do |format|
        format.html { redirect_to @book}
        format.js
    end
end

The view looks as such: 该视图如下所示:

<% if user_signed_in? && current_user.owns?(@book) %>
    <%= link_to book_own_path(@book), method: :delete, remote: true, class: "btn btn-danger btn-circle", title: "Remove from collection", data: { toggle: "tooltip", disable_with: "<span class='fa fa-minus'></span>"} do %><span class="fa fa-heart-o"></span><% end %>
<% else %>
    <%= link_to book_own_path(@book), method: :post, remote: true, class: "btn btn-success btn-circle", title: "Add to collection", data: { toggle: "tooltip", disable_with: "<span class='fa fa-plus'></span>"} do %><span class="fa fa-heart"></span><% end %>
<% end %>

So that when the button is clicked, it automatically adds a quantity of 1 to their inventory. 因此,单击该按钮时,它将自动向其库存添加数量1。 What I want to do is have the user be able to update their owned quantity from the book show view so I added this: 我想要做的是让用户能够从书展视图中更新其拥有的数量,因此我添加了以下内容:

<% if user_signed_in? && current_user.owns?(@book) %>
    <span id="<%= @book.id %>_quantity">
        <% Own.where(:user_id => current_user.id, :book_id => @book.id).each do |z| %>
        <% if z.quantity == 1 %>
            <form>
                You own <input type="text" placeholder="<%= z.quantity %>" id="quantity" name="quantity" size="1" class="text-center" /> copies of this book
                <input type="submit" onclick="<% Own.update(@own, :quantity => params[:quantity]) %>.submit();" hidden />
            <form>
        <% else %>
            <form>
                You own <input type="text" placeholder="<%= z.quantity %>" id="quantity" name="quantity" size="1" class="text-center" /> copies of this book
                <input type="submit" onclick="<% Own.update(@own, :quantity => params[:quantity]) %>.submit();" hidden />
            <form>
        <% end %>
    <% end %>
    <br />
    </span>
<% end %>

The above DOES update the own quantity when I click enter, BUT it redirects me to the same url with ?quantity=1 (or whatever the quantity value is) added to the end. 当我单击Enter时,上面的DOES会更新自己的数量,但会将我重定向到添加到末尾的?quantity = 1(或任何数量值)的相同URL。 It also does not show the quantity in the input placeholder unless the page is refreshed. 除非刷新页面,否则它也不显示输入占位符中的数量。

My question is, is there a better way to go about this, or is there a way to actually show the placeholder value. 我的问题是,是否有更好的方法可以解决此问题,或者是否有办法真正显示出占位符的价值。 Also, how could I set this where the form is submitted in the background instead of refreshing the page? 另外,如何设置此背景在后台提交表单而不是刷新页面?

To build your form in Rails, you should use what Rails gives you : Rails doc for Form helpers 要在Rails中构建表单,您应该使用Rails给您的内容: Form helper的Rails文档

or gems likes SimpleForm 或喜欢SimpleForm的宝石

This example assume you are using Rails 4+. 本示例假定您使用的是Rails 4+。

First, you want to display your book page, so load your book and load your owns (when you manipulates models is always better to do that in your controller) : 首先,您要显示您的书页,因此加载您的书并加载您自己的书(当您操纵模型时,最好在控制器中执行此操作):

# Books Controller
def show
  @book = Book.find(params[:id])
  @owns = current_user.owns.where(book: @book)
end

and your view, could now be something like this : 和您的视图,现在可能是这样的:

# Book show
<% @owns.each do |own| %>
  <div> You own <span class="<%= own.id %>_quantity"><%= own.quantity %></span> of this book </div>
  <%= form_for own, remote: true, method: :put do |f| %>
    <%= f.hidden_field :quantity, value: own.quantity + 1 %>
    <%= f.submit "Add One" %>
  <% end %>
  <hr>
<% end %>

We iterate through our owns and create a form which will add 1 to quantity. 我们遍历我们自己的,并创建一个将数量加1的表格。 The request will go to Own#update because of the PUT method on the form. 由于表单上的PUT方法,该请求将转到Own#update。 The form will be send via AJAX because of the attribute "remote: true" (This is one of the Rails ways to use AJAX in form : Rails doc for AJAX ). 表单将由于属性“ remote:true”而通过AJAX发送(这是Rails在表单中使用AJAX的一种方法: Rails doc for AJAX )。

# Own Controller
def update
  @own = Own.find(params[:id])
  respond_to do |format|
    if @own.update(own_params)
      format.html do
        redirect_to book_path(@own.book), notice: 'success'
      end
      format.js
    else
      format.html do
        redirect_to book_path(@own.book), alert: 'fail'
      end
    end
  end  
end

def own_params
  params.require(:own).permit(:quantity)
end

Here, we will load our Own and try to update it. 在这里,我们将加载自己的并尝试对其进行更新。 If JS is disabled, the request will take the HTML part and will redirect where you want. 如果禁用了JS,则请求将包含HTML部分,并将重定向到您想要的位置。 If JS is enabled, then you can create a "JS view", which are rendered exactly like the html one (you have to name them after the name of the action). 如果启用了JS,则可以创建一个“ JS视图”,其呈现方式与html视图完全相同(必须在操作名称后命名)。 So, it could be something like : 因此,可能类似于:

# views/owns/update.js.erb
$(".<%= @own.id %>_quantity").html("<%= @own.quantity %>");

It will replace the content of the span with the new quantity. 它将用新的数量替换范围的内容。

I haven't tested it, but at the end, your code could be something like this 我还没有测试过,但是最后,您的代码可能是这样的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM