使用复选框使用 AJAX 填充 rails 表单

Posted

技术标签:

【中文标题】使用复选框使用 AJAX 填充 rails 表单【英文标题】:Populating rails form with AJAX using checkbox 【发布时间】:2017-06-03 14:43:55 【问题描述】:

我很难集成 AJAX 调用来填充我的表单。我不知道我的格式是否正确,以及我应该使用什么来填写表单上的 JSON 数据。任何帮助深表感谢。

最终目标是能够单击复选框以在表单中填充新联系人的地址。我希望能够使用与他们所属的客户相同的地址填充地址。

我查看了使用 AJAX 将发货表单地址填充为与帐单表单地址相同的示例,但这对我不起作用,因为我在页面上没有两种地址表单。

这是新联系人查看页面的一部分:

  <div class='row'>
    <div class='col-sm-6 col-sm-offset-2'>
      <p>Address Same as Customer <input id="same_customer_address" name="accept" type="checkbox" value="1" /></p>
    </div>
  </div>

  <%= f.fields_for :address do |address| %>

    <div class="form-group">
      <%= address.label :line1, class: "col-sm-2 control-label" %>
      <div class="col-sm-6">
        <%= address.text_field :line1,class: "form-control", id: 'line1'%>
      </div>
    </div>

    <div class="form-group">
      <%= address.label :line2, class: "col-sm-2 control-label" %>
      <div class="col-sm-6">
        <%= address.text_field :line2,class: "form-control", id: 'line2'%>
      </div>
    </div>

    <div class="form-group">
      <%= address.label :city, class: "col-sm-2 control-label" %>
      <div class="col-sm-6">
        <%= address.text_field :city,class: "form-control", id: 'city' %>
      </div>
    </div>

    <div class="form-group">
      <%= address.label :state, class: "col-sm-2 control-label" %>
      <div class="col-sm-6">
        <%= address.text_field :state,class: "form-control", id: 'state' %>
      </div>
    </div>

    <div class="form-group">
      <%= address.label :zip, class: "col-sm-2 control-label", id: 'zip' %>
      <div class="col-sm-6">
        <%= address.text_field :zip,class: "form-control" %>
      </div>
    </div>

  <% end %>

Customer
has_many :contacts
belongs_to :address

Contact
belongs_to :address
belongs_to :customer

Contacts Controller
  def new
    authorize Contact
    @contact = @customer.contacts.new
    @contact.build_address
    phone_types = ['Cell','Work','Home']
    3.times  @contact.phones.build(phone_type: phone_types.shift) 
    @contact_types = @@contact_types
    # authorize @customer
  end

  def same_as_customer
    @customer = Customer.find(params[:id])
    respond_to do |format|
      format.html
      format.json  render json: @customer 
    end
  end
  private
  # Use callbacks to share common setup or constraints between actions.
  def set_customer
    @customer = Customer.find(params[:id])
  end

  def set_contact
    @contact = Contact.find(params[:contact_id])
  end
  # Never trust parameters from the scary internet, only allow the white list through.
  def contact_params
    params.require(:contact).permit(:first_name, :last_name, :email, :email_sec, :title, :contact_type,
     address_attributes: [ :line1, :line2, :city, :state, :zip, :id ],
     phones_attributes: [ :phone_type, :number, :id ])
  end
end

$('#same_customer_address').click(function() 
var customer_address;
$.ajax(
  type: 'GET',
  url: "/contacts/same_as_customer",
  datatype: "json",
  data:  line1: line1,
          line2: line2,
          city: city,
          state: state,
          zip: zip ,
  success: function(data)
    customer_address = data;
  
);
if ($("#same_customer_address").is(':checked')) 
  console.log("customer address is filled");
  $('#line1').val("customer_address.line1").val();
  $('#line2').val("customer_address.line2").val();
  $('#city').val("customer_address.city").val();
  $('#state').val("customer_address.state").val();
  $('#zip').val("customer_address.zip").val();
   else
    console.log("field is empty");
    $('#line1').val("");
    $('#line2').val("");
    $('#city').val("");
    $('#state').val("");
    $('#zip').val("");
  ;
);

【问题讨论】:

错误是什么? 现在我收到 Uncaught RangeError: Maximum call stack size exceeded in console。我不相信我的 ajax 调用正确或接收数据的表单正确。 您的应用程序中的联系人是否类似于订单? 联系人是为客户工作的人。就像企业和他们的员工一样。这是一个任务应用程序。 【参考方案1】:

检查这是否有效...

 $('#same_customer_address').change(function() 
  if(this.checked) 
    var customer_address;
    $.ajax(
      type: 'GET',
      url: "/contacts/same_as_customer",
      datatype: "json",
      success: function(data)
        customer_address = data;
        console.log("customer address is filled");
        $('#line1').val("customer_address.line1");
        $('#line2').val("customer_address.line2");
        $('#city').val("customer_address.city");
        $('#state').val("customer_address.state");
        $('#zip').val("customer_address.zip");
      
    );
   else 
    console.log("field is empty");
    $('#line1').val("");
    $('#line2').val("");
    $('#city').val("");
    $('#state').val("");
    $('#zip').val("");
  ;
);

# Contact Controller

  def same_as_customer
    @customer = Customer.find(params[:id])
    respond_to do |format|
      format.html
      format.json  render json: @customer.address 
    end
  end

替代方法

我是否可以建议一种替代方法...而不是填充表单,而是将该复选框的参数传递为 true 并在控制器中复制地址,然后保存记录。

【讨论】:

这不起作用我仍然得到:未捕获的 RangeError:超过最大调用堆栈大小。我需要更改我的表格以接受数据吗?如果我的表单中除了地址之外还有更多项目,我可以采用您的替代方法吗? 我想我们已经到了某个地方,现在我们得到了一个缺少的模板联系人/same_as_customer。我们希望它在联系人/新页面上呈现。【参考方案2】:

使用类而不是 id:

<div class='row'>
    <div class='col-sm-6 col-sm-offset-2'>
        <p>Address Same as Customer <input id="same_customer_address" name="accept" type="checkbox" value="1" /></p>
    </div>
</div>

<%= f.fields_for :address do |address| %>
    <div class="address-fields">
        <div class="form-group">
            <%= address.label :line1, class: "col-sm-2 control-label" %>
            <div class="col-sm-6">
                <%= address.text_field :line1, class: "form-control line1" %>
            </div>
        </div>

        <div class="form-group">
            <%= address.label :line2, class: "col-sm-2 control-label" %>
            <div class="col-sm-6">
                <%= address.text_field :line2, class: "form-control line2"%>
            </div>
        </div>

        <div class="form-group">
            <%= address.label :city, class: "col-sm-2 control-label" %>
            <div class="col-sm-6">
                <%= address.text_field :city, class: "form-control city" %>
            </div>
        </div>

        <div class="form-group">
            <%= address.label :state, class: "col-sm-2 control-label" %>
            <div class="col-sm-6">
                <%= address.text_field :state, class: "form-control state" %>
            </div>
        </div>

        <div class="form-group">
            <%= address.label :zip, class: "col-sm-2 control-label"%>
            <div class="col-sm-6">
                <%= address.text_field :zip, class: "form-control zip" %>
            </div>
        </div>
    </div>
<% end %>

现在让我们使用类将 JSON 值复制到输入:

var $form = $('#my_form_id');

$form.on('copy_address', function()
  $.getJSON("/contacts/same_as_customer").done(function(data)
    var attributes = ['line1', 'line2', 'city', 'state', 'zip'];
    $.each(attributes, function(i, attr)
      $fields.find('.form-control .' + attr).val(data[attr]);
    );
  );
);

$form.find('#same_customer_address').one('change', function()
   if (this.checked) 
     $form.trigger('copy_address');
   
);

【讨论】:

但是,您的方法的其余部分仍然有些破损 - URL 不采用 id 参数。并且该操作似乎没有返回包含地址的 JSON。我建议你从你当前的代码中退后一步,只是想一想。【参考方案3】:

所以我最终在后端填充了记录。它没有像我最初想要的那样填充表单,但它完成了我需要它做的事情,即更新地址记录。

联系人:

def create
    puts params.inspect
    authorize Contact

    @contact = @customer.contacts.new(contact_params)

    same_as_customer

    @contact.update(user_id: current_user.id.tap do |h|
                h[:address] =  @address if @address
            end
        )

    if @contact.save
        params[:contact][:emails].each do |email|
        @contact.emails.create(email:email)
      end

        redirect_to customer_account_url(@customer), notice: 'Contact created!'
    else
        @contact_types = @@contact_types
        @contact.errors.full_messages
        render :new
        # render json: @contact.errors, status: :unprocessable_entity
    end
  end

  def same_as_customer
    if params[:customers][:address] == '1'
         puts "checkbox is checked"
        @address = Address.create!(@customer.address.as_json.except('id'))
    else
         puts "checkbox is unchecked"
    end
  end

新的联系人视图:

<div class='row'>
    <div class='col-sm-6 col-sm-offset-2'>
      <p>Address Same as Customer <input id="same_customer_address" name="customers[address]" type="checkbox" value="1" /></p>
    </div>
</div>

【讨论】:

以上是关于使用复选框使用 AJAX 填充 rails 表单的主要内容,如果未能解决你的问题,请参考以下文章

无论如何用数组填充 UITableView 但保留复选标记?

在 Rails3 中选中或取消选中时,如何让复选框触发 ajax 调用?

Rails:使用 ajax 填充引导下拉列表

高级表单验证 - 如何在用户完成后在字段旁边添加复选标记? --Javascript [关闭]

使用 Remotipart 的 Rails AJAX 上传表单

Rails 5 ajax 表单:单击 Ajax 中的 2 个单选按钮之一提交表单