Rails 4 jQuery / Ajax для обновления и добавления элемента в частичное после создания

У меня есть форма с 2 вложенными формами. Я пытаюсь обновить вторую вложенную форму, когда первая форма используется для создания объекта, который вставляется во вторую форму.

Мой ajax работает, чтобы иметь возможность создавать и сохранять мой order_item, который создается моим первым f.fields_for: order_item, но я заблудился о том, как затем получить частичное обновление, которое находится в другом контроллере.

Вот моя родительская форма

<div class-"col-md-12">
<%= bootstrap_form_for(@quote) do |f| %>
<% if @quote.errors.any? %>
<div id="error_explanation">
    <h2><%= pluralize(@quote.errors.count, "error") %> prohibited this quote from being saved:</h2>

    <ul>
        <% @quote.errors.full_messages.each do |message| %>
        <li><%= message %></li>
        <% end %>
    </ul>
</div>
<% end %>
<%= f.hidden_field :quote_num, value:@current_user.company.starting_quote %>
<fieldset>
    <div class-"col-md-12">
        <div class="col-md-8">
            <%= f.collection_select :client_id, Client.order(:business_name), :id, :business_name, include_blank: true %>
        </div>
        <div class="col-md-4">
            <%= f.date_select :quote_exp, :order => [:month, :day, :year] %>
        </div>
        <div class="margin-bottom-10"></div>
        <div class="col-md-6">
            <%= f.grouped_collection_select :billing_address, Client.order(:business_name), :addresses, :business_name, :full_address, :full_address, include_blank: true %>
        </div>
        <div class="col-md-6">
            <%= f.grouped_collection_select :shipping_address, Client.order(:business_name), :addresses, :business_name, :full_address, :full_address, include_blank: true %>
        </div>
    </div>
</fieldset>
<div class="margin-bottom-10"></div>
<hr />
<div class="margin-bottom-10"></div>

<!-- Render Select Options for New Item -->
<div class="col-md-12">
    <%= f.fields_for :order_item do |ff| %>
    <div class="col-md-4">
        <%= ff.hidden_field :quote_id, value: @quote.id %>
        <%= ff.collection_select :category_id, Category.order(:name), :id, :name, include_blank: "Select Category", hide_label: true %>
    </div>
    <div class="col-md-6">
        <%= ff.grouped_collection_select :product_id, Category.order(:name), :products, :name, :id, :name, include_blank: true, hide_label: true %>
    </div>
    <div class="col-md-2">
        <%= ff.submit "Add Item", class:"btn-u btn-u-blue pull-right", id:"add_item" %>
    </div>
    <% end %>
</div>

<div class="margin-bottom-10"></div>
<hr />
<div class="margin-bottom-10"></div>
<div class="table-search-v1 margin-bottom-20">
    <div class="table-responsive">
        <table class="table table-hover table-bordered table-striped table-condensed">
            <thead>
                <th style="width: 20px;"></th>
                <th style="width: 300px;">Product</th>
                <th>Price</th>
                <th style="width: 20px;">Quantity</th>
                <th>Discounts</th>
                <th>Total</th>
            </thead>
            <tbody id="list">
                <!-- this is where we display the results -->
                <%= f.fields_for :order_items do |builder| %>
                    <%= render 'order_item_fields', f: builder, show_total: true %>
                <% end %>

            </tbody>
        </table>

    </div>
</div>
</div>
<div class="margin-bottom-10"></div>
<hr />
<div class="margin-bottom-10"></div>
<fieldset>

    <div class="col-md-12">
        <div class="col-md-6">
            <%= f.text_area :special_note, rows:7, label:"Special Notes" %>
        </div>
        <div class="col-md-6">
            <div id="total_deposit">
            </div>
            <div class="col-md-4">
                <h5>Sales Tax</h5>
            </div>
            <div class="col-md-8">
                <%= f.text_field :tax_amount, hide_label: true %>
            </div>
            <div class="col-md-4">
                <h5>Sub-Total</h5>
            </div>
            <div class="col-md-8">
                <%= f.text_field :sub_total, hide_label: true %>
            </div>
            <div class="col-md-4">
                <h5>Shipping</h5>
            </div>
            <div class="col-md-8">
                <%= f.text_field :shipping_cost, hide_label: true %>
            </div>
            <div class="col-md-4">
                <h5>Total</h5>
            </div>
            <div class="col-md-8">
                <%= f.text_field :total, hide_label: true %>
            </div>
        </div>
    </div>
</fieldset>
<div class="margin-bottom-10"></div>
<hr />
<div class="margin-bottom-10"></div>
<div class="tag-box tag-box-v1 box-shadow shadow-effect-1 col-md-12">
    <h4>Deposit</h4>
    <%= f.check_box :deposit, label: "Require Deposit" %>
    <%= f.text_field :deposit_amount, hide_label: true, placeholder:"Enter Amount" %>
</div>
<div class="margin-bottom-10"></div>
<div class="tag-box tag-box-v1 box-shadow shadow-effect-1 col-md-12">
    <h4>Shipping Information</h4>
    <div class="col-md-6">
        <select class="form-control" id="shipping">
            <option value="0" selected="selected">Not Applicable</option>
            <option>Overnight Shipping</option>
            <option>2 Day Shipping</option>
            <option>3 Day Shipping</option>
            <option>Ground (5-7 days)</option>
        </select>
    </div>
    <div class="col-md-6">
        <%= f.text_field :shipping_cost, hide_label: true, placeholder:"Enter Amount" %>
    </div>
</div>
<div class="actions">
    <%= f.submit "Save Quote", class:"btn-u pull-right" %>
</div>
<% end %>
</div>
<script>
$("#quote_deposit").change(function(){
    $("#quote_deposit_amount").toggle($(this).is(':checked'));
});

$('#quote_deposit').trigger('change');

var product = $("#quote_product_id").val()

</script>

Вот моя вложенная форма, которая отображается строкой в ​​моей таблице в моей основной форме. Это часть, которая должна обновляться после создания, чтобы показать все элементы, связанные с цитатой. Если возможно, я бы хотел добавить только элемент и использовать js, чтобы не обновлять весь фрагмент.

<fieldset>
<tr>
    <td>
        <div class="btn-group">
            <button type="button" class="btn-u dropdown-toggle" data-toggle="dropdown">
                <i class="fa fa-angle-down"></i>
            </button>
            <ul class="dropdown-menu" role="menu">
                <li><%= f.hidden_field :_destroy %>
                <%= link_to "Remove Item", '#', class: "remove_fields btn btn-link" %></li>
                <li><button class="btn btn-link">Add Custom Item</button></li>
                <li><button class="btn btn-link">Remove Item</button></li>
            </ul>
        </div>
    </td>
    <td>
        <h5><%= f.object.product.name %></h5>
    </td>
    <td>
        <h5 class="text-right"><span style="color: green"> <%= number_to_currency f.object.unit_price %></span></h5>
    </td>
    <td>
        <%= f.number_field :quantity, min: 1, hide_label: true %>
        <%= f.hidden_field :_destroy %>
    </td>
    <td>
        <%= f.text_field :discount, hide_label: true %>
    </td>
    <td>
        <h5 class="text-right"><span style="color: green"><%= number_to_currency f.object.total_price %></span></h5>
    </td>
</tr>
</fieldset>

Мой JQuery AJAX вызов для создания объекта

$('form').on 'click', '#add_item', (e) ->
e.preventDefault()
product = $('#quote_order_item_product_id :selected').val()
quote = $('#quote_order_item_quote_id').val()
console.log(product)
console.log(quote)
$.ajax '/order_items',
  type: 'POST'
  dataType: 'json'
  data: { order_item: { product_id: product, quote_id: quote } }
  success:(data) ->
    alert data.id
  error: (jqXHR, textStatus, errorThrown) ->
    alert textStatus

И мои заказы создают метод создания

def create
@order_item = OrderItem.new(order_item_params)
 respond_to do |format|
   if @order_item.save
     format.js do
        render 'quotes/' + @quote.id + '/refresh'
     end
   else
     format.json { render json: @order_item.errors, status: :unprocessable_entity }
   end
  end
 end

1 ответ

Решение

После создания правильного маршрута из quote:id/order_item я затем отредактировал свой контроллер, чтобы он возвращал только js (или json, не имеет значения) в случае успеха. Затем я изменил свой метод jquery coffeescript, чтобы он выглядел следующим образом.

$('form').on 'click', '#add_item', (e) ->
e.preventDefault()
product = $('#quote_order_item_product_id :selected').val()
product_name = $('#quote_order_item_product_id :selected').text()
console.log(product_name)
count = $('.order-item').length
console.log(count)
quote = $('#quote_order_item_quote_id').val()
console.log(product)
console.log(quote)
$.ajax '/order_items',
  type: 'POST'
  dataType: 'json'
  data: { order_item: { product_id: product, quote_id: quote } }
  success:(data) ->
    id = data.id.toString()
    $root = $('.order-item:last').clone()

    $root.find(".remove_fields").attr('name',"quote[order_items_attributes][#{count}][_destroy]" )
    $root.find(".remove_fields").attr('id',"quote_order_items_attributes_#{count}__destroy]" )
    $root.find(".product").text(product_name)
    $root.find(".product-id").attr('value', product)
    $root.find(".price").text(data.unit_price)
    $root.find(".quantity_input").val("1")
    $root.find(".discount_input").val("")
    $root.find(".quantity_input").attr('name',"quote[order_items_attributes][#{count}][quantity]" )
    $root.find(".quantity_input").attr('id',"quote_order_items_attributes_#{count}_quantity]" )
    $root.find(".discount_input").attr('name',"quote[order_items_attributes][#{count}][discount]" )
    $root.find(".discount_input").attr('id',"quote_order_items_attributes_#{count}_discount]" )

    $root.appendTo('#list')

  error: (jqXHR, textStatus, errorThrown) ->
    alert textStatus

По сути, то, что я делаю, происходит успешно, я возвращаю свой объект как (данные), а затем клонирую предыдущую строку таблицы и перестраиваю свою форму на стороне клиента со всеми правильными входными значениями. Вы можете создать его с помощью javascript, я уверен, но моя форма довольно сложная и довольно длинная, так что, хотите верьте, хотите нет, это был короткий путь.

Другие вопросы по тегам