Search code examples
ruby-on-railsajaxsimple-form

Dynamically fill form fields according to value change of a dropdown before submitting form


I am working on an order form of a RoR project and want to fill buyer info with existing customer info in database. So I need to select a customer name from a dropdown(select field) then fill in buyer info fields (name, phone, email, address like so) with selected customer's information.

Therefore my question is, what's the preferred practise of doing this? My thought is something like an Ajax call with GET method to get json format data then use jQuery to fill in or change buyer info fields. Is it the correct "rails way" to achieve this function?

BTW, the whole order form is simple_form, and buyer info fields are all in a simple_fields_for section. If this helps.


Solution

  • The "standard" way of doing this would be via ajax (just send a JSON request to your users#show action, and it should return the user data you request -- I'll write in a second).


    From your question, it seems you should do something else.

    fill buyer info with existing customer info in database

    This is bad practice -- it will lead to duplicate entries in your db.

    The way this should be done is to take advantage of the associations inside Rails to allow you to associate a customer with new buyer info:

    #app/models/order.rb
    class Order < ActiveRecord::Base
       belongs_to :customer #-> requires "customer_id" in "orders" table
    end
    
    #app/models/customer.rb
    class Customer < ActiveRecord::Base
       has_many :orders
    end
    

    This will create an associative customer object on your order: @order.customer which will return the data in your other db table.

    You'll have to make sure you populate the customer_id param for your new Order object:

    #app/controllers/orders_controller.rb
    class OrdersController < ApplicationController
       def new
          @customers = Customer.all
          @order = Order.new
       end
    
       def create
          @order = Order.new order_params
          @order.save
       end
    
       private
    
       def order_params
          params.require(:order).permit(:customer_id, :etc, :etc)
       end
    end
    
    #app/views/orders/new.html.erb
    <%= form_for @order do |f| %>
       <%= f.collection_select :customer_id, @customers, :id, :name %>
       <%= f.submit %>
    <% end %>
    

    JS

    You can use what you're asking with the above code, too.

    You basically need to send an Ajax (JSON) request to your customers#show action, which will return the relevant fields for a specific customer to your JS:

    #app/controllers/customers_controller.rb
    class CustomersController < ApplicationController
       respond_to :json, :html, only: :show
    
       def show
          @customer = Customer.find params[:id]
          respond_with @customer
       end
    end
    
    #app/assets/javascripts/application.js
    $(document).on("change", "select#customer_id", function(e){
       $.ajax({
          url: "customers",
          dataType: "json",
          data: { id: $(this).val() },
          success: function(data){
             // Output returned data in form
          }
       });
    });