通过Ajax提交表单并刷新一个fields_for部分-响应中未定义的局部变量f

问题描述 投票:2回答:2

[有很多有关Rails表单和简单ajax crud接口的资源,例如那些著名的Post->注释示例。但是,我的问题有点复杂,我似乎无法正常工作。

我有一个订单表格,可以包含多个line_items。在ryan bates借助nested_form gem提交任何内容之前,添加和删除了这些line_items。很好,它可以完美地工作。

现在,我想添加一些动态行为。当某些line_item输入字段更改时,总计和其他计算应更新。为该line_item选择其他产品时,应在提交表单之前更新并显示其价格。像那样的东西。我的第一种方法是使用JavaScript进行这些计算,在工作的同时,我很快意识到我无论如何都要将我在应用程序模型中定义的所有逻辑加倍。另外,在JS中这样做很麻烦,因为您无权访问实例变量。

[经过一番思考,我想在有人更改某些输入值后立即提交并刷新这些field_for line_item部分。这应该是基本的工作流程:

[用户输入->提交订单(如果可能,也可以只是line_item)->返回更新的line_item部分,其中包含刷新的计算信息,等等。

将来,我希望将此行为扩展到不再需要保存按钮的地步。

但是我不想重新渲染整个表单(对于快速的用户输入来说太慢了,只渲染当前的fields_for部分。)>

问题是,每当我将js响应限制为重新呈现当前的fields_for部分时,form_for @order do |f|中所需的f变量都会丢失。如果我在回复中替换了整个表格,则效果很好。

这是当前代码:

/ views / orders / _form.html.slim

= nested_form_for @order do |f|
  ...
  #line-items
    = f.fields_for :line_items do |line_item|
      = render "orders/line_item_fields", f: line_item
  ...

views / orders / _line_item_fields.html.slim

...

= f.label :product_id, "Product"
= f.collection_select(:product_id, Product.order(:name), :id, :name, class: "order_line_items_product_id submittable" )

= f.label :quantity
= f.text_field :quantity, class: "submittable"

= f.label :price
= f.text_field :price, class: "submittable"

...

.totals
  p
    span = f.object.total_price

/ app / assets / javascripts / orders.js.erb

$('body').on('change', '.submittable', function () {
  var current_item = $(this).closest('section')
  var order_id = $('form.edit_order').data('order-id')
  var data = $('form.edit_order').serialize();

  current_item.addClass('item-to-refresh')

  $.ajax({
    url: "/orders/" + order_id,
    data: data,
    dataType: "script",
    type: "patch",
    error: function(response) {
      response
    },
    success: function(response){
      response
    }
  });
}

/ app / controllers / orders_controller.rb

...

def update
  @order = Order.find(params[:id])
  authorize @order

  if @order.update_attributes(order_params)
    respond_to do |format|
      format.html do
        redirect_to order_path
        flash[:success] = "Order #{@order.id} saved"
      end
      format.js
    end
  else
    render 'edit'
  end

end

...

/ app / views / orders / update.js.erb

$('.item-to-refresh').replaceWith("<%= j render 'orders/line_item_fields' %>")

如上所述,响应始终带有错误ActionView::Template::Error (undefined local variable or method 'f' for #class...-我知道它需要f变量,但是如何传递它呢?我尝试将主题上的f: ff: line_item和类似变体从update.js.erb

添加到呈现函数,但没有成功。自然,如果我不尝试在响应中呈现表单元素,而是通过简单的<p>It works!</p>,整个过程将完美无缺地运行

而且,我在这里想到的一般概念是处理Web应用程序交互性的好方法吗?这仍然是一个老式文档/基于页面的应用程序,重新加载页面就可以了。但是对于应用程序的某些部分,用户只是希望获得即时反馈和结果-如今,点击“保存”以获取一些计算和总计是不够的。另一方面(除非上面的代码没有告诉您),我讨厌Javascript,并且喜欢在解决这些问题的同时尽量减少使用Javascript。因此,我想找到一种可重用的方式来提交和刷新变更事件的部分内容。

[有很多有关Rails表单和简单ajax crud接口的资源,例如那些著名的Post->注释示例。但是,我的问题有点复杂,我似乎无法理解...

javascript ruby-on-rails ajax forms nested-forms
2个回答
0
投票

尝试一下


0
投票

我知道有些晚了,但是我有一个同样的问题,我想在更新记录而不呈现完整的表单后重新呈现fields_for表单。

© www.soinside.com 2019 - 2024. All rights reserved.