
在现代 Web 应用中,用户经常需要输入结构化数据,其中某些字段的值依赖于其他字段的选择。当这种依赖关系需要应用于一个可以动态添加多行的表单时,实现起来会变得更具挑战性。本教程将指导您如何构建一个设备修改日志系统,该系统允许用户在单页上添加多条修改记录,每条记录都包含一个“子系统”下拉菜单和一个动态加载的“组件”下拉菜单,其中“组件”列表会根据所选的“子系统”实时更新。
首先,我们需要定义用于存储子系统和组件信息的数据库表,并建立数据库连接。
数据库表结构:
lu_subsystem (子系统查找表) | 字段 | 类型 | 描述 | | :----------- | :---------- | :----------- | | id | INT(11) | 主键,自增 | | subsystem_name | VARCHAR(255)| 子系统名称 |
lu_component (组件查找表) | 字段 | 类型 | 描述 | | :----------- | :---------- | :----------- | | component_id | INT(11) | 主键,自增 | | subsystem_id | INT(11) | 外键,关联 lu_subsystem.id | | component_name | VARCHAR(255)| 组件名称 |
database_connection.php - 数据库连接与辅助函数:
立即学习“PHP免费学习笔记(深入)”;
此文件负责建立与 MySQL 数据库的连接,并提供两个 PHP 函数用于从数据库中获取下拉菜单选项。
<?php
// database_connection.php
// 建立 PDO 数据库连接
$connect = new PDO("mysql:host=localhost; dbname=bunker_logs;", "root", "");
$connect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 设置错误模式为抛出异常
/**
* 从 lu_subsystem 表中获取所有子系统作为下拉菜单选项。
*
* @param PDO $connect 数据库连接对象。
* @return string 包含 <option> 标签的 HTML 字符串。
*/
function fill_subsystem_options($connect)
{
$query = "SELECT id, subsystem_name FROM lu_subsystem ORDER BY subsystem_name ASC";
$statement = $connect->prepare($query);
$statement->execute();
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
$output = '';
foreach($result as $row)
{
$output .= '<option value="'.$row["id"].'">'.$row["subsystem_name"].'</option>';
}
return $output;
}
/**
* 根据给定的子系统 ID 从 lu_component 表中获取相应的组件作为下拉菜单选项。
*
* @param PDO $connect 数据库连接对象。
* @param int $subsystem_id 子系统 ID。
* @return string 包含 <option> 标签的 HTML 字符串。
*/
function get_component_options_by_subsystem($connect, $subsystem_id)
{
// 使用预处理语句防止 SQL 注入
$query = "SELECT component_id, component_name FROM lu_component WHERE subsystem_id = :subsystem_id ORDER BY component_name ASC";
$statement = $connect->prepare($query);
$statement->bindParam(':subsystem_id', $subsystem_id, PDO::PARAM_INT);
$statement->execute();
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
$output = '';
foreach($result as $row)
{
$output .= '<option value="'.$row["component_id"].'">'.$row["component_name"].'</option>';
}
return $output;
}
?>注意事项:
这个 PHP 文件将作为前端 AJAX 请求的端点,负责接收子系统 ID,并返回对应的组件列表。
<?php
// fetch_components.php (原 fill_component.php)
include('database_connection.php');
if (isset($_POST["subsystem_id"]) && !empty($_POST["subsystem_id"])) {
// 调用辅助函数获取组件选项
echo get_component_options_by_subsystem($connect, $_POST["subsystem_id"]);
} else {
// 如果没有提供 subsystem_id,返回一个默认选项
echo '<option value="">Select Subsystem First</option>';
}
?>这是实现多行动态依赖下拉菜单的核心文件。它包含 HTML 结构、引入必要的 JavaScript 库(jQuery 和 Bootstrap),以及处理动态行添加/删除和下拉菜单依赖逻辑的 jQuery 代码。
<?php
// index.php
include('database_connection.php'); // 引入数据库连接和辅助函数
?>
<!DOCTYPE html>
<html>
<head>
<title>动态依赖下拉菜单实现多行输入</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<style>
body { padding-top: 20px; }
.container { max-width: 960px; }
</style>
</head>
<body>
<div class="container">
<h3 align="center">使用 Ajax jQuery 和 PHP 实现动态添加/删除依赖下拉菜单行</h3>
<br />
<h4 align="center">输入设备修改详情</h4>
<br />
<form method="post" id="insert_form">
<div class="table-responsive">
<span id="error"></span>
<table class="table table-bordered" id="item_table">
<thead>
<tr>
<th>输入项目名称</th>
<th>子系统</th>
<th>组件</th>
<th><button type="button" name="add" class="btn btn-success btn-xs add"><span class="glyphicon glyphicon-plus"></span></button></th>
</tr>
</thead>
<tbody>
<!-- 初始行或动态添加的行将在这里 -->
</tbody>
</table>
<div align="center">
<input type="submit" name="submit" class="btn btn-info" value="插入数据" />
</div>
</div>
</form>
</div>
<script>
$(document).ready(function(){
var count = 0; // 用于跟踪动态生成行的唯一标识符
// 动态添加行
$(document).on('click', '.add', function(){
count++; // 每次添加行,计数器递增,确保每个新行有唯一的 ID
var html = '';
html += '<tr>';
html += '<td><input type="text" name="item_name[]" class="form-control item_name" /></td>';
// subsystem_id 下拉菜单,使用 data-row-id 属性来关联当前行的组件下拉菜单
html += '<td><select name="subsystem_id[]" class="form-control subsystem_id" data-row-id="'+count+'"><option value="">选择子系统</option><?php echo fill_subsystem_options($connect); ?></select></td>';
// item_component_id 下拉菜单,其 ID 包含 count,以便在 JS 中精确选择
html += '<td><select name="item_component_id[]" class="form-control item_component_id" id="item_component_id_'+count+'"><option value="">选择组件</option></select></td>';
html += '<td><button type="button" name="remove" class="btn btn-danger btn-xs remove"><span class="glyphicon glyphicon-minus"></span></button></td>';
$('tbody').append(html); // 将新行添加到表格的 tbody 中
});
// 动态删除行
$(document).on('click', '.remove', function(){
$(this).closest('tr').remove(); // 找到最近的父级 <tr> 并移除
});
// 处理子系统下拉菜单的改变事件,实现组件的动态加载
$(document).on('change', '.subsystem_id', function(){
var selectedSubsystemId = $(this).val(); // 获取当前选中的子系统 ID
var currentRowId = $(this).data('row-id'); // 获取当前行的唯一 ID
var targetComponentDropdown = $('#item_component_id_' + currentRowId); // 根据行 ID 找到对应的组件下拉菜单
if (selectedSubsystemId) { // 只有当选择了有效的子系统时才发送 AJAX 请求
$.ajax({
url: "fetch_components.php", // AJAX 请求的后端接口
method: "POST",
data: { subsystem_id: selectedSubsystemId }, // 发送子系统 ID
success: function(data)
{
var html = '<option value="">选择组件</option>'; // 默认选项
html += data; // 追加从后端返回的组件选项
targetComponentDropdown.html(html); // 更新组件下拉菜单的内容
},
error: function() {
targetComponentDropdown.html('<option value="">加载组件失败</option>'); // 错误处理
}
});
} else {
// 如果未选择子系统,清空组件下拉菜单并显示默认提示
targetComponentDropdown.html('<option value="">选择组件</option>');
}
});
// 表单提交处理
$('#insert_form').on('submit', function(event){
event.preventDefault(); // 阻止表单默认提交行为
var error = '';
// 简单的前端验证
$('.item_name').each(function(index){ // index 从 0 开始
if($(this).val() == '')
{
error += '<p>请在第 ' + (index + 1) + ' 行输入项目名称</p>';
return false;
}
});
$('.subsystem_id').each(function(index){
if($(this).val() == '')
{
error += '<p>请在第 ' + (index + 1) + ' 行选择子系统</p>';
return false;
}
});
$('.item_component_id').each(function(index){
if($(this).val() == '')
{
error += '<p>请在第 ' + (index + 1) + ' 行选择组件</p> ';
return false;
}
});
var form_data = $(this).serialize(); // 序列化表以上就是使用 PHP、MySQL 和 jQuery 实现多行动态依赖下拉菜单的详细内容,更多请关注php中文网其它相关文章!
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号