Как создать динамическую форму, в которой поля, не принадлежащие таблице / форме, влияют на выбор параметров - PullRequest
1 голос
/ 17 октября 2019

Я могу создать форму заказа, где пользователь может заполнить bike_type и, следовательно, форма отображает велосипеды, принадлежащие этому bike_type.

  • Заказы связаны с велосипедами через таблицу соединений (так как между ними существует отношение многих ко многим).
  • Велосипед принадлежит к байту_типа
  • Abike_type принадлежит к bike_store

Issue

Когда форма перерисовывается, например, (i) повышается валидация, поэтому «новое» действие отображается снова или(ii) когда я хочу изменить заказ:

  • Все поля заполняются предыдущими данными, кроме полей для bike_type и bike (они пусты).

Код

Контроллер заказов

class OrdersController < ApplicationController
  def new
    @bike_store = BikeStore.find(params[:bike_store_id])
    @order = Order.new
    @order.order_bikes.build
    @bike_type_list = @bike_store.bike_types
    @bikes = []

    # Display bikes for category
    if params[:bike_type].present?
      @bikes = BikeType.find(params[:bike_type]).bikes
    end
    if request.xhr?
      respond_to do |format|
        format.json {
        render json: {bikes: @bikes}
      }
      end
    end
    authorize @order
  end

  def create
    @order = Order.new(order_params)
    @bike_store = BikeStore.find(params[:bike_store_id])
    @order.bike_store = @bike_store
    authorize @order
    @order.save
    if @order.save
      redirect_to bike_store_path(@bike_store)
    else
      @bike_type_list = @bike_store.bike_types
      render 'new'
    end
  end

  def edit
    @bike_store = BikeStore.find(params[:bike_store_id])
    @order = Order.find(params[:id])
    @bike_type_list = @bike_store.bike_types
    @bikes = @order.bikes
    authorize @order
  end

  def update
    @bike_store = BikeStore.find(params[:bike_store_id])
    @order = Order.find(params[:id])
    @bikes = @order.bikes
    if @order.update(order_params)
      redirect_to redirect_to bike_store_path(@bike_store)
    else
      render 'edit'
    end
      authorize @order
  end

    private
  def set_order
    @order = Order.find(params[:id])
  end

  def order_params
    params.require(:order).permit(:arrival, :departure, :payment,
      order_bikes_attributes: [:id, :bike_id, :bike_quantity, :_destroy,
        bikes_attributes: [:id,:name, :bike_type_id,
          bike_types_attributes: [:id, :name]]])
  end
end

Просмотров / Order / _form

<%= simple_form_for [@bike_store, @order] do |f|%>
  <%= f.simple_fields_for :order_bikes do |order_bike| %>
    <%= order_bike.simple_fields_for :bikes do |bike| %>
      <%= bike.input :bike_type, collection: @bike_type_list, input_html:{
        id: "bike_type"
      }%>
    <%= order_bike.association :bike, collection: @bikes, input_html:{
      value: @bikes.object_id,
      id: "dynamic-bikes"
    } %>
    <% end %>
  <% end %>
<% end %>

<script >
  // dynamic bikes for change category
  $(document).on("change", "#bike_type", function(){
    var bike_type = $(this).val();

    $.ajax({
      url: "/bike_stores/<%= @bike_store.id %>/orders/new",
      method: "GET",
      dataType: "json",
      data: {bike_type: bike_type},
      error: function (xhr, status, error) {
        console.error('AJAX Error: ' + status + error);
      },
      success: function (response) {
      var bikes = response["bikes"];
      $("#dynamic-bikes").empty();

      $("#dynamic-bikes").append('<option>Select bike</option>');
      for(var i=0; i< bikes.length; i++){
        $("#dynamic-bikes").append('<option value="' + bikes[i]["id"] + '">' + bikes[i]["name"] + '</option>');
      }
    }
  });
  });
  // dynamic bikes for releading form (e.g. new)
   $(document).ready(function(){
    var bike_type = $("#bike_type").val();

    $.ajax({
      url: "/bike_stores/<%= @bike_store.id %>/orders/new",
      method: "GET",
      dataType: "json",
      data: {bike_type: bike_type},
      error: function (xhr, status, error) {
        console.error('AJAX Error: ' + status + error);
      },
      success: function (response) {

      var bikes = response["bikes"];
      $("#dynamic-bikes").empty();

      $("#dynamic-bikes").append('<option>Select bike</option>');
      for(var i=0; i< bikes.length; i++){
        $("#dynamic-bikes").append('<option value="' + bikes[i]["id"] + '">' + bikes[i]["name"] + '</option>');
      }
    }
  });
  });
</script>

1 Ответ

1 голос
/ 17 октября 2019

Похоже, вы хотите сохранить «состояние» страницы формы до отправки формы на ту же страницу формы после отправки (при возникновении ошибки проверки). Обычно вам просто нужно «воспроизвести» события Javascript, которые произошли на предыдущей странице , и поэтому «обычно» ниже должно быть достаточно для того, чтобы это работало:

TL; DR:

app / views / order / _form.html.erb:

<!-- ... -->
<!-- ... -->
<script>
  // on document ready (after all DOM elements have been loaded):
  $(function() {
    // replay event by immediately triggering a
    // "change" event on your `#bike_type` input
    $('#bike_type').change();
  })

  // dynamic bikes for change category
  $(document).on("change", "#bike_type", function(){
    // ...
    // ...
  })

  // ...
  // ...
</script>
...