【问题标题】:Pre-populate Rails collection_select with ajax action (Rails 5 and jQuery)使用 ajax 操作预填充 Rails collection_select(Rails 5 和 jQuery)
【发布时间】:2023-03-10 08:25:01
【问题描述】:

我正在尝试构建一个发票应用程序,其中每个发票都有一个行发票项目(例如产品名称、成本、金额)

我希望当我从发票项目的 下拉列表 中选择 productname 时,会触发一个 ajax 来查询 product 数据库表 与 params[:product_id],从数据库中获取产品 cost 并因此立即填充项目成本。

即当用户选择产品名称时,无需输入该产品成本就会立即显示出来。

在下面的附图中,我的 query_string 按预期返回 JSON,除了我不知道如何将返回的 data 传递/显示到 cost_field

如果我执行 html(product.cost),我会在 #notification 中获取/返回 [object, object] 并在 undefind cost 中导轨控制台也是如此。

我的问题是,我该如何做这样的事情? $("#notification").html(product.cost)

型号:

    class Invoice < ApplicationRecord
      has_many :items, dependent: :destroy
      accepts_nested_attributes_for :items, allow_destroy: true,  reject_if: proc {|a| a[:product_id].blank?}
      has_many :products, through: :item
    end

    class Item < ApplicationRecord
      belongs_to :invoice, optional: true
      belongs_to :item, optional: true
    end

    class Product < ApplicationRecord
      has_many :items
    end

控制器

   class InvoicesController < ApplicationController
      before_action :set_invoice, only: [:show, :edit, :update, :destroy]


   def index
     @invoices = Invoice.all
   end

   def new
     @invoice = Invoice.new
     2.times {  @invoice.items.build }
   end

   def pricedata
    @product = Product.select(:id, :cost, :productname).where('products.id = ?', params[:product_id])

     respond_to do |format|
     format.html {  render html: @product.id }
     format.js #{ render js: @product}
     format.json { render json: @product }
   end

  private
     def invoice_params
        params.require(:invoice).permit(:name, :amount, items_attributes: [:qty, :price, :id, :product_id, :_destroy])
     end

表格

     <p id="notification"></p>   # notice to keep my eyes on return obj

    ...

    <%= f.fields_for :items do |item| %>

     <span><%= item.label :product_id %>      </span>


     <span>       // # collection begins here
       <%= item.collection_select(:product_id, Product.all, :id, :productname,
            {prompt: "Select a product"}, 
            {class: 'selectors'  multiple: true })  
       %>
      </span>     // # collection ends here


     <span><%= item.label :qty %> </span>
     <span><%= item.number_field :qty %> </span>
     <span><%= item.label :price, class: "p_price"   %> </span>
     <span><%= item.number_field :price %> </span> 
     <span><%= item.check_box :_destroy %> Remove item</span>

    ...

JAVASCRIPT / 咖啡

  $(document).ready ->
    $('.selectors').on "change", ->
    selectOptions= $('.selectors option:selected')
    product_id = $(this).val()

    if selectOptions.length > 0
        selectOptions.each ->
            $.ajax({
                url: '/invoices/:id/pricedata?product_id=' + product_id,
                type: 'GET',
                dataType: 'html',
                contentType: 'application/html'
                success: (product)-> 
                        $("#noticification").html(product)
                        console.log(product)
                    })

【问题讨论】:

  • 按照@max 的建议,我能够解决问题。我像这样直接向 ProductController 发送 ajax 请求..... $.ajax({ url: '/products/' + product_id, ..... $("#notification").html (product.cost) })

标签: javascript jquery ruby-on-rails ruby-on-rails-5


【解决方案1】:

你真的太复杂了。要获取产品的详细信息,您只需向 ProductsController 上的简单显示操作发送 ajax 请求即可。

class ProductsController < ApplicationController
  # GET /products/:id
  def show
    @product = Product.find(params[:id])
    respond_to do |format|
     format.html
     format.json { render json: @product }
    end
  end
end

此外,在这种情况下,您不应使用多项选择,因为这会使数量和价格变得不明确。而是为每个项目行创建一个字段集或 div。 fields_for 帮助器可用于为每个项目指定特定范围:

<%= form_for(@invoice) do %>
  # ...
  <%= fields_for(:items) do |item| %>
    <!-- group each item in an element so you can find the associated inputs -->
    <div class="item">
     <!-- use a div to group inputs ands labels instead! -->
     <span><%= item.label :product_id %>      </span>
     <span><%= item.collection_select(:product_id, Product.all, :id, :productname,
            {prompt: "Select a product"}, 
            {class: 'selectors'  multiple: true })  %>
     </span>     // # collection ends here
     <span><%= item.label :qty %> </span>
     <span><%= item.number_field :qty %> </span>
     <span><%= item.label :price, class: "p_price"   %> </span>
     <span><%= item.number_field :price %> </span> 
     <span><%= item.check_box :_destroy %> Remove item</span>
    </div>
  <% end %>
  # ...
<% end %>

【讨论】:

  • 如果您想解释为什么您当前的解决方案不起作用,因为.where 返回的是记录集合而不是单个记录。虽然您可以使用 .take 或使用 .find 修复它,但您的方法已被破坏,可以以更简单、更传统的方式完成。
  • 谢谢@max。解决了。我将立即发布我的解决方案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-03
  • 2011-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
相关资源
最近更新 更多