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

如何用jQuery实现含数据库联动下拉框与价格输入框的动态字段添加?

Dynamic Repeatable Form with Linked Category/Product Dropdowns

Got it, let's build this dynamic form step by step. We'll create repeatable field groups (each with a category dropdown, product dropdown, and price input) where:

  • Categories load from your database on page load
  • Products auto-update based on the selected category
  • Users can add/remove field groups using jQuery

1. HTML Base Structure

First, set up the core HTML. We'll use a container to hold all dynamic field groups, plus an "Add More" button. Each group includes a remove button for cleanup.

<div class="container mt-4">
  <h3>Product Entries</h3>
  <div id="form-container">
    <!-- Initial form group -->
    <div class="form-group row mb-3">
      <div class="col-md-4">
        <label>Category</label>
        <select class="form-control category-select" required>
          <option value="">Select Category</option>
          <!-- Categories will be populated via JS -->
        </select>
      </div>
      <div class="col-md-4">
        <label>Product</label>
        <select class="form-control product-select" required>
          <option value="">Select Category First</option>
        </select>
      </div>
      <div class="col-md-3">
        <label>Price</label>
        <input type="number" class="form-control price-input" step="0.01" required>
      </div>
      <div class="col-md-1 align-self-end">
        <button type="button" class="btn btn-danger remove-btn">X</button>
      </div>
    </div>
  </div>
  <button type="button" id="add-more" class="btn btn-primary mt-2">Add More</button>
</div>

2. jQuery & JavaScript Logic

This handles loading categories, linking categories to products, adding new fields, and removing fields. We'll use event delegation to ensure dynamically added elements work correctly.

$(document).ready(function() {
  // Load initial categories on page load
  loadCategories();

  // Load categories from backend API
  function loadCategories() {
    $.ajax({
      url: 'get-categories.php', // Replace with your backend endpoint
      type: 'GET',
      dataType: 'json',
      success: function(categories) {
        $('.category-select').each(function() {
          $(this).html('<option value="">Select Category</option>');
          $.each(categories, function(index, category) {
            $(this).append(`<option value="${category.id}">${category.name}</option>`);
          }.bind(this));
        });
      },
      error: function() {
        alert('Failed to load categories.');
      }
    });
  }

  // Load products based on selected category
  $(document).on('change', '.category-select', function() {
    const categoryId = $(this).val();
    const productSelect = $(this).closest('.form-group').find('.product-select');

    if (categoryId) {
      $.ajax({
        url: 'get-products.php', // Replace with your backend endpoint
        type: 'GET',
        data: { category_id: categoryId },
        dataType: 'json',
        success: function(products) {
          productSelect.html('<option value="">Select Product</option>');
          $.each(products, function(index, product) {
            productSelect.append(`<option value="${product.id}">${product.name}</option>`);
          });
        },
        error: function() {
          alert('Failed to load products.');
        }
      });
    } else {
      productSelect.html('<option value="">Select Category First</option>');
    }
  });

  // Add new form group
  $('#add-more').click(function() {
    const lastFormGroup = $('.form-group').last().clone();
    // Reset all values in the cloned group
    lastFormGroup.find('.category-select').val('');
    lastFormGroup.find('.product-select').html('<option value="">Select Category First</option>');
    lastFormGroup.find('.price-input').val('');
    // Append the new group to the container
    $('#form-container').append(lastFormGroup);
  });

  // Remove form group (hide the remove button if only one group left)
  $(document).on('click', '.remove-btn', function() {
    if ($('.form-group').length > 1) {
      $(this).closest('.form-group').remove();
    } else {
      alert('You need at least one product entry.');
    }
  });
});

3. Backend Example (PHP/MySQL)

Here's a simple backend implementation to fetch categories and products from a MySQL database. Adjust the table/column names to match your schema.

get-categories.php

<?php
// Database connection (replace with your credentials)
$conn = new mysqli('localhost', 'username', 'password', 'database_name');

if ($conn->connect_error) {
  die("Connection failed: " . $conn->connect_error);
}

$query = "SELECT id, name FROM categories ORDER BY name";
$result = $conn->query($query);

$categories = [];
while ($row = $result->fetch_assoc()) {
  $categories[] = $row;
}

echo json_encode($categories);
$conn->close();
?>

get-products.php

<?php
$conn = new mysqli('localhost', 'username', 'password', 'database_name');

if ($conn->connect_error) {
  die("Connection failed: " . $conn->connect_error);
}

$categoryId = $_GET['category_id'] ?? '';
if (!$categoryId) {
  echo json_encode([]);
  exit;
}

// Use prepared statement to prevent SQL injection
$query = "SELECT id, name FROM products WHERE category_id = ? ORDER BY name";
$stmt = $conn->prepare($query);
$stmt->bind_param("i", $categoryId);
$stmt->execute();
$result = $stmt->get_result();

$products = [];
while ($row = $result->fetch_assoc()) {
  $products[] = $row;
}

echo json_encode($products);
$stmt->close();
$conn->close();
?>

4. Optional CSS (Bootstrap Compatible)

To make the form look clean, add these styles (or use Bootstrap directly):

.form-group {
  padding: 10px;
  border: 1px solid #eee;
  border-radius: 5px;
  margin-bottom: 15px;
}

.remove-btn {
  width: 100%;
}

内容的提问来源于stack exchange,提问作者Nishu Kashyap

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:32:40