I am relatively new in JS/Ajax and I am note sure how to render dynamic options, based on previous inserted data in the same (simple_)form.
Context: Via the application a bike shop chain ('chains') can rent out
Outstanding question: I am able to get the bike_type_id via JS. How can I use this id of the bike_type to show the bikes belonging to that bike_type in the same form?
As mentioned, unfortunately I am not really familiar with the usage of JS/Ajax in a rails apps, so it would be really appreciated and helpful if paths of the files could be added where the suggested code should be written (eg app/javascript/components/order.js etc.)
Final notes:
models
class Order < ApplicationRecord
belongs_to :bike_store
has_many :bike_types, through: :bike_store
has_many :order_bikes, inverse_of: :order, dependent: :destroy
accepts_nested_attributes_for :order_bikes, allow_destroy: true
end
class OrderBike < ApplicationRecord
belongs_to :bike
belongs_to :order
accepts_nested_attributes_for :bike
end
class Bike < ApplicationRecord
belongs_to :bike_type
validates :name, presence: true
has_many :order_bikes
has_many :orders, through: :order_bikes
end
class BikeType < ApplicationRecord
belongs_to :bike_store
has_many :bikes, dependent: :destroy
accepts_nested_attributes_for :bikes, allow_destroy: true
has_many :bike_options, dependent: :destroy
accepts_nested_attributes_for :bike_options, allow_destroy: true
validates :name, :bike_count, presence: true
end
class BikeStore < ApplicationRecord
has_many :bike_types, dependent: :destroy
has_many :orders, dependent: :destroy
end
order controller
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
end
def create
@order = Order.new(order_params)
@bike_store = BikeStore.find(params[:bike_store_id])
@order.bike_store = @bike_store
@order.save
redirect_to root_path
end
private
def order_params
params.require(:order).permit(:arrival, :departure,
order_bikes_attributes: [:id, :bike_id,:bike_quantity, :_destroy,
bikes_attributes: [:id, :name,
bike_types_attributes: [:id, :name]]])
end
end
views/orders/new.html.erb
<%= simple_form_for [@bike_store, @order] do |f|%>
<%= f.simple_fields_for :order_bikes do |order_bike| %>
<%= order_bike.input :bike_quantity %>
<%= order_bike.simple_fields_for :bikes do |bike| %>
#fist a bike_type will be classified, see below
<%= bike.select :bike_type_id, options_for_select(@bike_type_list.collect{|type|[type.name, type.id]}) %>
<% end %>
#then a dropdown of bikes belonging to above chose bike_type need to be displayed below.
<%= order_bike.association :bike, collection [bike_type.bikes] %>
<% end %>
<%= f.input :arrival %>
<%= f.input :departure %>
<%= f.submit %>
<% end %>
<script>
// return id bike_type
function selectType(){
const bikeType = document.getElementById("order_order_bikes_attributes_0_bikes_bike_type_id").value;
}
</script>
Wow figuring this out was painful/took some time.... For the people looking at this, I found a working answer, hope it saves you some time.
I'm pretty sure it is not the most elegant solution, so please feel free to optimize. I did it with Ajax, please find the solution below:
In the view
<%= simple_form_for [@bike_store, @order] do |f|%>
<%= f.simple_fields_for :order_bikes do |order_bike| %>
<%= order_bike.input :bike_quantity %>
<%= order_bike.simple_fields_for :bikes do |bike| %>
#fist a bike_type will be classified, see below
<%= bike.select :bike_type_id, options_for_select(@bike_type_list.collect{|type|[type.name, type.id]}) %>
<% end %>
#then a dropdown of bikes belonging to above chose bike_type need to be displayed below.
<%= order_bike.association :bike, collection [bike_type.bikes] %>
<% end %>
<%= f.input :arrival %>
<%= f.input :departure %>
<%= f.submit %>
<% end %>
<script>
$(document).on("change", "#order_order_bikes_attributes_0_bikes_bike_type_id", 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) {
console.log(response);
var bikes = response["bikes"];
$("#order_order_bikes_attributes_0_bikes_bike_type_id").empty();
$("#order_order_bikes_attributes_0_bike_id").append('<option>Select bike</option>');
for(var i=0; i< bikes.length; i++){
$("#order_order_bikes_attributes_0_bike_id").append('<option value="' + bikes[i]["id"] + '">' + bikes[i]["name"] + '</option>');
}
}
});
});
</script>
order controller
def new
@bike_store = BikeStore.find(params[:bike_store_id])
@order = Order.new
@order.order_bikes.build
@bike_type_list = @bike_store.bike_types
if params[:bike_type].present?
@bikess = BikeType.find(params[:bike_type]).bikes
end
if request.xhr?
respond_to do |format|
format.json {
render json: {bikes: @bikes}
}
end
end
end
end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.