如何使用 AJAX 更新 simple_form 输入字段?
How do I update a simple_form input field using AJAX?
我有一个 simple_form 输入字段,它是我需要在 onchange 时异步更新的表单的一部分事件被触发。
我需要更新的字段显示为 select 框,因为它是一个集合。但是集合表示嵌套集合模型的记录。因此,当用户 select 具有特定值时,我希望能够使用其子项更新同一字段,并让用户可以选择选择任何子项作为同一字段的值。
问题是,如何在不触及表单其余部分的情况下仅更新该字段。
只是想了解一下我当前的设置:
表单看起来像这样:
<%= simple_form_for @product, html: {class: 'form-horizontal'} do |f| %>
<%= f.input :product_name %>
<%= f.association :location, collection: @locations, input_html: { data: {remote: :true, url: "/update_locations"} } %>
<%= f.submit 'Post', class: 'btn btn-default btn-lg' %>
<% end %>
@产品是一个新的产品,其中belongs_to位置,
@locations 是 Location 的集合,其中每个 has_many 产品
因此使用 simple_form association 方法
位置也acts_as_nested_set
我的 routes.rb
里有这个
get 'update_locations' => 'products#update_locations'
我需要帮助完成控制器操作:
def update_locations
@product = Product.new
@location = Location.find_by_id(params[:product][:location_id])
@locations = @location.children
# TODO: render code that updates the simple_form field with
# the new @locations collection
end
我不确定上面的控制器应该呈现的部分视图中应该包含什么代码。
问题是我不知道如何只更新 simple_form 中的一个元素。
我对 AJAX 和 rails 的使用也有非常松散的把握,不知道你可以为同一个控制器同时拥有 HTML 和 JS 局部视图,因此我试图适应我的所有代码在 HTML 中,这会很麻烦并且不引人注目 JavaScript。
偶然发现 jQuery 方法 replaceWith 也很有帮助。
有了这些知识,我就能完成我打算要做的事情。
我创建了一个 JavaScript 局部视图,它是响应 AJAX 调用而呈现的。部分渲染了一个 .html.erb 部分视图,它用更新的元素重建了一个 simple_form 。然后 JS 视图从重建的表单中提取更新的元素,并使用 jQuery replaceWith() 方法仅替换初始表单中的特定元素,同时保持表单的其余部分不变。
这是 JS 部分 (location.js.erb) 的样子:
var updatedLocations = $('#product_location_id', $('<%= j render "updateLocations" %>'))
$('#product_location_id').replaceWith(updatedLocations)
而 HTML erb 部分 (updateLocations.html.erb) 看起来像这样:
<%= simple_form_for @product, html: {class: 'form-horizontal'} do |f| %>
<%= f.association :location, collection: @locations, input_html: { data: {update_locations: "true", remote: :true, url: "/update_locations"} } %>
<% end %>
控制器:
def update_locations
@product = Product.new
@location = Location.find_by_id(params[:product][:location_id])
@locations = @location.children
if @locations.empty?
render nothing: true
else
render partial: 'locations'
end
end
我有一个 simple_form 输入字段,它是我需要在 onchange 时异步更新的表单的一部分事件被触发。
我需要更新的字段显示为 select 框,因为它是一个集合。但是集合表示嵌套集合模型的记录。因此,当用户 select 具有特定值时,我希望能够使用其子项更新同一字段,并让用户可以选择选择任何子项作为同一字段的值。
问题是,如何在不触及表单其余部分的情况下仅更新该字段。
只是想了解一下我当前的设置: 表单看起来像这样:
<%= simple_form_for @product, html: {class: 'form-horizontal'} do |f| %>
<%= f.input :product_name %>
<%= f.association :location, collection: @locations, input_html: { data: {remote: :true, url: "/update_locations"} } %>
<%= f.submit 'Post', class: 'btn btn-default btn-lg' %>
<% end %>
@产品是一个新的产品,其中belongs_to位置, @locations 是 Location 的集合,其中每个 has_many 产品 因此使用 simple_form association 方法 位置也acts_as_nested_set
我的 routes.rb
里有这个get 'update_locations' => 'products#update_locations'
我需要帮助完成控制器操作:
def update_locations
@product = Product.new
@location = Location.find_by_id(params[:product][:location_id])
@locations = @location.children
# TODO: render code that updates the simple_form field with
# the new @locations collection
end
我不确定上面的控制器应该呈现的部分视图中应该包含什么代码。
问题是我不知道如何只更新 simple_form 中的一个元素。 我对 AJAX 和 rails 的使用也有非常松散的把握,不知道你可以为同一个控制器同时拥有 HTML 和 JS 局部视图,因此我试图适应我的所有代码在 HTML 中,这会很麻烦并且不引人注目 JavaScript。
偶然发现 jQuery 方法 replaceWith 也很有帮助。
有了这些知识,我就能完成我打算要做的事情。
我创建了一个 JavaScript 局部视图,它是响应 AJAX 调用而呈现的。部分渲染了一个 .html.erb 部分视图,它用更新的元素重建了一个 simple_form 。然后 JS 视图从重建的表单中提取更新的元素,并使用 jQuery replaceWith() 方法仅替换初始表单中的特定元素,同时保持表单的其余部分不变。
这是 JS 部分 (location.js.erb) 的样子:
var updatedLocations = $('#product_location_id', $('<%= j render "updateLocations" %>'))
$('#product_location_id').replaceWith(updatedLocations)
而 HTML erb 部分 (updateLocations.html.erb) 看起来像这样:
<%= simple_form_for @product, html: {class: 'form-horizontal'} do |f| %>
<%= f.association :location, collection: @locations, input_html: { data: {update_locations: "true", remote: :true, url: "/update_locations"} } %>
<% end %>
控制器:
def update_locations
@product = Product.new
@location = Location.find_by_id(params[:product][:location_id])
@locations = @location.children
if @locations.empty?
render nothing: true
else
render partial: 'locations'
end
end