You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Rails中通过点击按钮使用jQuery创建动态重复div的实现方法

Got it! Let’s walk through how to add dynamic duplicate divs to your Rails form using jQuery (or vanilla JavaScript if you’d prefer) — this will let users click a plus button to add new expense rows easily:

Step 1: Adjust Your Rails Form HTML

First, structure your form to include a container for dynamic rows, an initial row, and an "Add" button. We’ll use a reusable class (expense-row) for the rows we want to duplicate:

<%= form_for @expense_fills, url: view_excess_path, method: :post do |f| %>
  <div class="row">
    <div class="col-xs-12">
      <div class="box">
        <div class="box-header">
          <h3 class="box-title text-center">Expense Fills</h3>
          <!-- Add Button -->
          <button type="button" id="add-expense-row" class="btn btn-success pull-right">+ Add Expense</button>
        </div>
        <div class="box-body">
          <!-- Container to hold all dynamic rows -->
          <div id="expense-rows-container">
            <!-- Initial expense row (this will be cloned) -->
            <div class="row expense-row" style="margin-left: 20%">
              <div class="col-xs-4 col-sm-4">
                <%= f.text_field :amount, placeholder: "Amount", class: "form-control" %>
              </div>
              <div class="col-xs-4 col-sm-4">
                <%= f.text_field :description, placeholder: "Description", class: "form-control" %>
              </div>
              <div class="col-xs-2 col-sm-2">
                <button type="button" class="btn btn-danger remove-row">- Remove</button>
              </div>
            </div>
          </div>
        </div>
        <div class="box-footer">
          <%= f.submit "Submit", class: "btn btn-primary" %>
        </div>
      </div>
    </div>
  </div>
<% end %>
Step 2: jQuery Implementation

Add this script (either in your application.js file or a dedicated JS file) to handle cloning rows and removing them:

$(document).ready(function() {
  // Handle adding new expense rows
  $('#add-expense-row').click(function() {
    // Clone the first existing expense row
    const $newRow = $('.expense-row:first').clone();
    
    // Clear input values so the new row is empty
    $newRow.find('input').val('');
    
    // Update input names to use array syntax (critical for Rails to parse params correctly)
    $newRow.find('input').each(function() {
      const currentName = $(this).attr('name');
      // Replace any existing index with empty brackets to create an array
      const newName = currentName.replace(/\[\d+\]/g, '[]');
      $(this).attr('name', newName);
      // Update the ID to avoid duplicates (optional but follows HTML best practices)
      $(this).attr('id', `${currentName.replace(/[\[\]]/g, '_')}_${Date.now()}`);
    });
    
    // Append the new row to the container
    $('#expense-rows-container').append($newRow);
  });
  
  // Handle removing rows (use event delegation for dynamically added elements)
  $(document).on('click', '.remove-row', function() {
    // Prevent removing the last row (adjust this if you want to allow empty forms)
    if ($('.expense-row').length > 1) {
      $(this).closest('.expense-row').remove();
    } else {
      alert('You need at least one expense row!');
    }
  });
});
Step 3: Vanilla JavaScript Alternative

If you don’t want to use jQuery, here’s the same functionality with plain JS:

document.addEventListener('DOMContentLoaded', function() {
  const addButton = document.getElementById('add-expense-row');
  const container = document.getElementById('expense-rows-container');
  
  // Add new row
  addButton.addEventListener('click', function() {
    const firstRow = document.querySelector('.expense-row');
    const newRow = firstRow.cloneNode(true);
    
    // Clear input values
    const inputs = newRow.querySelectorAll('input');
    inputs.forEach(input => {
      input.value = '';
      // Update name attribute for Rails array parsing
      let currentName = input.getAttribute('name');
      const newName = currentName.replace(/\[\d+\]/g, '[]');
      input.setAttribute('name', newName);
      // Update ID to avoid duplicates
      input.setAttribute('id', `${currentName.replace(/[\[\]]/g, '_')}_${Date.now()}`);
    });
    
    container.appendChild(newRow);
  });
  
  // Remove row (event delegation)
  document.addEventListener('click', function(e) {
    if (e.target.classList.contains('remove-row')) {
      const rows = document.querySelectorAll('.expense-row');
      if (rows.length > 1) {
        e.target.closest('.expense-row').remove();
      } else {
        alert('You need at least one expense row!');
      }
    }
  });
});
Important Rails Backend Notes

To properly handle the submitted data in your controller, make sure you permit the array parameters. For example:

def expense_fill_params
  # If params[:expense_fills] is an array of hashes
  params.require(:expense_fills).map do |fill|
    fill.permit(:amount, :description)
  end
end

If you’re using nested attributes with a parent model, you’ll also need to add accepts_nested_attributes_for :expense_fills to your parent model, and adjust the params to permit expense_fills_attributes: [:amount, :description].

内容的提问来源于stack exchange,提问作者Bharat Mane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:18:25