簡體   English   中英

如何在Ruby On Rails中自動完成表單字段

[英]How to complete form fields automatically in Ruby On Rails

問候! 我正在創建一個庫存系統,其中在進行銷售時,我需要編寫代碼或產品名稱,我需要從中獲取價格,而無需手動編寫,但是我幾乎沒有掌握javascript知識,我發現了jquery的自動完成之類的幾種資源,但是,我做不到,我遵循了有關動態選擇器的RailsCasts教程,盡管如此,我還是需要使用文本字段來實現這一點,我非常感謝有人可以幫助我,特別是在輸出模型中,我在output_item模型中有商品,在我的產品模型中:

output_form.html.erb

<%= form_with(model: output, local: true, id: "form") do |f| %>

          <div class="form-group">
            <%= f.label :invoice %> <br>
            <%= f.text_field :invoice, class: "form-control", placeholder: "CE0001" %>
          </div>      

          <div class="form-group">
            <%= f.label :customer %> <br>
            <%= f.text_field :customer, class: "form-control", placeholder: "Ej. Jeovanny" %>
          </div>

          <table width="100%" id="output-item">
            <thead>
              <th>Product</th>
              <th>Quantity</th>
              <th>Price</th>
              <th>Total</th>
              <th>Options</th>
            </thead>
            <tbody>
              <%= f.fields_for :output_items, id: "form" do |item| %>
                <%= render "output_item_fields", f: item %>
              <% end %>
            </tbody>
          </table>

          <div class="form-group mb-0">
            <%= link_to_add_association 'Add product', f, :output_items, :"data-association-insertion-node" => "table#output-item",:"data-association-insertion-method" => "append", class: "btn btn-success" %>        
          </div>      

      <div class="form-group>
          <%= link_to "Cancelar", outputs_path, class: "btn btn-danger" %>        
          <%= f.submit "Send", class: "btn btn-primary" %>  
      </div>        

<% end %>

output_items_fields.html.erb

<tr class="item">
    <td><%= f.text_field :product_id, class: "form-control field" %></td>
    <td><%= f.text_field :quantity, class: "form-control field quantity" %></td>
    <td><%= f.text_field :price, class: "form-control field price" %></td>
    <td><input type="text" class="form-control field subtotal"></td>
    <td class="text-center">
        <%= link_to_remove_association f, { wrapper_class: "item", class: "btn btn-danger" } do %>
            <i class="fal fa-trash-alt"></i>
        <% end %>
    </td>
</tr>

product.rb

class Product < ApplicationRecord

    has_many :input_items
    has_many :output_items
    validates :code, :name, presence: true

    def purchase
        input_items.pluck(:quantity).sum
    end

    def sale
        output_items.pluck(:quantity).sum
    end

    def stock
        (input_items.pluck(:quantity).sum - output_items.pluck(:quantity).sum)
    end

    def price
        self.input_items.sum(:price) / self.input_items.count
    end

end

Output.rb

class Output < ApplicationRecord

    has_many :output_items, inverse_of: :output, :dependent => :delete_all
    accepts_nested_attributes_for :output_items, reject_if: :all_blank, allow_destroy: true    

    validates :invoice, :provider, presence: true

end

output_item.rb

class OutputItem < ApplicationRecord

    belongs_to :product
    belongs_to :output
    validates :quantity, :price, numericality: true, presence: true  

end

class Product < ApplicationRecord

    has_many :output_items

end

input.rb

class Input < ApplicationRecord

    has_many :input_items, inverse_of: :input, :dependent => :delete_all
    accepts_nested_attributes_for :input_items, reject_if: :all_blank, allow_destroy: true    

    validates :invoice, :provider, presence: true

end

input_item.rb

class InputItem < ApplicationRecord

  belongs_to :product
  belongs_to :input
  validates :quantity, :price, numericality: true, presence: true

end

input_migrate.rb

class CreateInputs < ActiveRecord::Migration[5.2]
  def change
    create_table :inputs do |t|
      t.string :invoice
      t.string :provider

      t.timestamps
    end
  end
end

input_items_migration.rb

class CreateInputItems < ActiveRecord::Migration[5.2]
  def change
    create_table :input_items do |t|
      t.integer :product_id
      t.float :quantity
      t.float :price
      t.belongs_to :input, foreign_key: true

      t.timestamps
    end
  end
end

product_migrate.rb

class CreateProducts < ActiveRecord::Migration[5.2]
  def change
    create_table :products do |t|
      t.string :code
      t.string :name
      t.float :utility

      t.timestamps
    end
  end
end

output_migrate.rb

class CreateOutputs < ActiveRecord::Migration[5.2]
  def change
    create_table :outputs do |t|
      t.string :invoice
      t.string :customer

      t.timestamps
    end
  end
end

output_item_migrate.rb

class CreateOutputItems < ActiveRecord::Migration[5.2]
  def change
    create_table :output_items do |t|
      t.integer :product_id
      t.float :quantity
      t.float :price
      t.belongs_to :output, foreign_key: true

      t.timestamps
    end
  end
end

RailsCast提供給自動完成選擇器的代碼是:

(function() {
    jQuery(function() {
      var states;
      $('#input_price').parent().hide();
      states = $('#input_price').html();
      return $('#input_product_id').change(function() {
        var country, escaped_country, options;
        country = $('#input_product_id :selected').text();
        escaped_country = country.replace(/([ #;&,.+*~\':"!^$[\]()=>|\/@])/g, '\\$1');
        options = $(states).filter("optgroup[label='" + escaped_country + "']").html();
        if (options) {
          $('#input_price').html(options);
          return $('#input_price').parent().show();
        } else {
          $('#input_price').empty();
          return $('#input_price').parent().hide();
        }
      });
    });

  }).call(this); 

謝謝,以什么方式可以適應這種變化,或者最方便的方法是作為補充數據,我將繭用於動態物品,我非常感謝,可以為我提供幫助!


更新

output_items_fields.html.erb

<tr class="item">
    <td><%= f.text_field :product_id, class: "form-control field" %></td>
    <td><%= f.text_field :quantity, class: "form-control field quantity" %></td>
    <td><%= f.text_field :price, class: "form-control field price" %></td>
    <td><input type="text" class="form-control field subtotal"></td>
    <td class="text-center">
        <%= link_to_remove_association f, { wrapper_class: "item", class: "btn btn-danger" } do %>
            <i class="fal fa-trash-alt"></i>
        <% end %>
    </td>
</tr>

<% content_for :javascript do %> 
  <script type="text/javascript">var product_info = $.parseJSON('<%= @product_info.to_json.html_safe %>');</script>
<% end %>

<% content_for :javascript do %> 
    <script type="text/javascript">
      var product_info = $.parseJSON('<%= @product_info.to_json.html_safe %>');
      (function() {
          jQuery(function() {
            var product = product_info[$('#output_product_id')]
            return $('#output_product_id').change(function() {
            if (product) {                     
              $('#output_price').val(product.price);
              $('#output_description').val(product.description);
            } else {
              $('#output_price').val("");
              }
            });
          });
        }).call(this); 
    </script>
<% end %>

output_controller.rb

class OutputsController < ApplicationController
  before_action :set_output, only: [:show, :edit, :update, :destroy]

  def new
    @output = Output.new
    @output.output_items.build
    @product_info = Product.joins(:input_items).select(:price).all.inject({}) {|a, b| a[b.input_items] = {price: b.price}}  
  end
end

當我在瀏覽器控制台中查找product_info並進行測試時,我得到了:

console.log(product_info)
Object { price: null }
debugger eval code:1:1
undefined

console.log('testing')
testing debugger eval code:1:1
undefined

只要您沒有太多的產品,這就是我要解決的問題,以便根據型號自動填充(如果我正確理解了您的要求)。 本質上,您需要獲取所有產品數據的Javascript表示,然后將其提供給jQuery進行填充,這與Railscast使用國家/地區名稱的方式類似。 幸運的是,您可以使用.to_json輕松將ruby Hash或Array轉換為Javascript可以看到的內容。

首先,創建一個具有產品價格關鍵產品模型的哈希,然后從您的數據源中填充它:

@product_info = Product.select(:code,:price).all.inject({}) {|a, b| a[b.code] = {price: b.price}}

並將其放入您的控制器操作中。

接下來,將該實例變量放入頁面上的Javascript變量中。 這部分取決於您是否設置為使用content_for:javascript-請參見在rails中包括使用content_for的嵌入式javascript

<% content_for :javascript do %> 
  <script type="text/javascript">
    var product_info = $.parseJSON(<%= @product_info.to_json.html_safe %>);
  </script>
<% end %>

最后,將Railscast代碼上的代碼添加到content_for塊中,使其看起來像以下內容(替換舊的content_for:javascript塊)。 這部分取決於您-如果您想要一個剛剛填充的文本框,或者想要它們所擁有的,則可以在哈希表中查找值的地方隱藏並顯示該字段。 我只是將其填充(如果可以找到),或者將其填充為空白字符串(如果找不到)

<% content_for :javascript do %> 
    <script type="text/javascript">
      var product_info = $.parseJSON(<%= @product_info.to_json.html_safe) %>;
      (function() {
          jQuery(function() {
            return $('#input_product_id').change(function() {
            if (var product = product_info[$('#input_product_id')]) {
              $('#input_price').val(product.price);
            } else {
              $('#input_price').val("");
              }
            });
          });
        }).call(this); 
    </script>
<% end %>

問題/替代

現在,它可以像第一次迭代一樣正常工作,但是取決於您的設置方式,它可能會涉及一些問題。

您擁有的產品越多,作為JSON字符串吐出的數據就越多。 如果該字符串變為2、4、10兆字節,則確實會減慢您的用戶的速度,因為他們必須加載該數據才能查看您的頁面。 您可以通過選擇一條不同的路線並觸發AJAX調用來緩解這種情況,因為在用戶鍵入型號編號時將獲得產品數據,並按照此處的操作填充字段。 只要您確定在用戶每次在文本字段中鍵入內容時都會命中一個終結點,並且需要進行相應的數據庫調用來進行搜索,沿着這條路線走就沒有太多的工作了。

另一個問題是,每次頁面加載時,您將重新獲取所有產品數據。 您將需要開始考慮在視圖或控制器中緩存該數據,以便始終從緩存加載產品模型->價格/描述映射,而不是從數據庫中獲取數據。

最后,如果其他用戶輸入了您想用來為自動填充代碼提供動力的產品信息,則需要重新加載頁面。 如果您沒有添加/更改太多產品,那么就不用擔心了,但是如果每分鍾/小時更改多次,則您可能需要考慮采用上述解決方案來觸發AJAX每次用戶輸入內容時都會調用,這樣就可以保證返回最新的產品信息,而不是所有產品信息的某些陳舊表示形式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM