Select
基于使用 PHP
的另一个 select
,仅在添加新行时不起作用。
如需演示,请访问here (参见演示步骤)
- 页面加载时有两行,它们按需要工作。 (服务选项按照项目选项)
- 点击“添加行”按钮,将添加另一行
- 新插入的行不起作用。 (服务选择没有给出任何选项,因为前两个给出)
我尝试过的:
<?php require_once '../home.php' ?>
<?php
if( $_SERVER['REQUEST_METHOD']=='POST' && isset( $_POST['action'], $_POST['id'] ) && $_POST['action']=='get_dependant_menu' ){
ob_clean();
$action=filter_input( INPUT_POST, 'action', FILTER_SANITIZE_STRING );
$id=filter_input( INPUT_POST, 'id', FILTER_SANITIZE_STRING );
if( $action && $id && !is_nan( $id ) ){
$stmt=$user_home->runQuery("SELECT * FROM service WHERE IRN=:irn ORDER BY Sr ASC ");
$stmt->bindParam(':irn',$id);
$stmt->execute();
$stmtin=$user_home->runQuery("SELECT * FROM item WHERE IRN=:irn ORDER BY Sr ASC ");
$stmtin->bindParam(':irn',$id);
$stmtin->execute();
$rowin=$stmtin->fetch( PDO::FETCH_ASSOC );
if( $stmt->rowCount() > 0 ){
echo "<option value='Select Service'>Select Service ({$rowin['Name']})</option>";
while( $row=$stmt->fetch( PDO::FETCH_ASSOC ) ){
echo "<option value='{$row['SRN']}'>{$row['Name']}</option>";
}
}
}
exit();
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type='text/javascript' charset='utf-8'>
function ajax(m,u,p,c,o){
var xhr=new XMLHttpRequest();
xhr.onreadystatechange=function(){
if( xhr.readyState==4 && xhr.status==200 )c.call( this, xhr.response, o, xhr.getAllResponseHeaders() );
};
var params=[];
for( var n in p )params.push(n+'='+p[n]);
switch( m.toLowerCase() ){
case 'post': p=params.join('&'); break;
case 'get': u+='?'+params.join('&'); p=null; break;
}
xhr.open( m.toUpperCase(), u, true );
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xhr.send( p );
}
function createmenu(r,o,h){
o.menu.innerHTML=r;
}
function bindEvents(){
var oSelItem=document.querySelector('select[name="item1"]');
var oSelService=document.querySelector('select[name="service1"]');
oSelItem.onchange=function(e){
var method='post';
var url=location.href;
var params={
'action':'get_dependant_menu',
'id':this.options[ this.options.selectedIndex ].value
};
var opts={
menu:oSelService
};
ajax.call( this, method, url, params, createmenu, opts );
}.bind( oSelItem );
}
document.addEventListener( 'DOMContentLoaded', bindEvents,false );
</script>
</head>
<body>
<form method="post" action="invoice_form.php" id="item_sel">
<table id="chiru_inv" class="table table-striped table-hover table-bordered table-responsive">
<tr>
<td colspan="3">
<input type="text" name="customer" value="" placeholder="Customer Name">
</td>
</tr>
<tr>
<th>Item</th>
<th>Service</th>
<th>Qty</th>
</tr>
<tr>
<td>
<select name='item1' class='country'>
<option value="Select Item">Select Item</option>
<?php
//$sql='select * from `item` order by `Sr` asc;';
$stmt=$user_home->runQuery("SELECT * FROM item ORDER BY Sr ASC ");
$stmt->execute();
if( $stmt->rowCount() > 0 ){
while( $row=$stmt->fetch( PDO::FETCH_ASSOC ) ){
echo "<option value='{$row['IRN']}'>{$row['Name']}</option>";
}
}
?>
</select></td>
<td><select class="country" name="service1">
</select></td>
<td><input type="text" name="qty1" value="" placeholder="Quantity"></td>
</tr>
<tr>
<td>
<select name='item2' class='country'>
<option>Select Item</option>
<?php
$stmt=$user_home->runQuery("SELECT * FROM item ORDER BY Sr ASC ");
$stmt->execute();
if( $stmt->rowCount() > 0 ){
while( $row=$stmt->fetch( PDO::FETCH_ASSOC ) ){
echo "<option value='{$row['IRN']}'>{$row['Name']}</option>";
}
}
?>
</select></td>
<td><select class="country" name="service2">
</select></td>
<td><input type="text" name="qty2" value="" placeholder="Quantity"></td>
</tr>
<tr>
<td colspan="3"><button type="submit" name="btnsave" class="btn btn-default">
<span class="glyphicon glyphicon-save"></span> Save
</button>
</td>
</tr>
</table>
<input type="button" class="add-row" value="Add Row">
</form>
<div id="markup_model" class="hide">
<table>
<tr>
<td>
<select name="nameitem" class="country">
<option>Select Item</option>
<?php
$stmt=$user_home->runQuery("SELECT * FROM item ORDER BY Sr ASC ");
$stmt->execute();
if( $stmt->rowCount() > 0 ){
while( $row=$stmt->fetch( PDO::FETCH_ASSOC ) ){
echo "<option value='{$row['IRN']}'>{$row['Name']}</option>";
}
}
?>
</select>
</td>
<td>
<select class="country" name="namewhat"></select>
</td>
<td>
<input type="text" name="nameqty" value="" placeholder="Quantity" />
</td>
</tr>
</table>
</div>
</div>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var cont = 3
var qty = "qty"
var item = "item"
var what = "service"
$(".add-row").click(function() {
var nameqty = qty + cont;
var nameitem = item + cont;
var namewhat = what + cont;
var markup = $('#markup_model tbody');
$(markup).find('.country:eq(0)').attr('name', nameitem);
$(markup).find('.country:eq(1)').attr('name', namewhat);
$(markup).find('input').attr('name', nameqty);
$(markup.html()).insertBefore($('button[type="submit"]').closest("tr"));
cont++;
});
});
</script>
<script type='text/javascript' charset='utf-8'>
function ajax(m,u,p,c,o){
var xhr=new XMLHttpRequest();
xhr.onreadystatechange=function(){
if( xhr.readyState==4 && xhr.status==200 )c.call( this, xhr.response, o, xhr.getAllResponseHeaders() );
};
var params=[];
for( var n in p )params.push(n+'='+p[n]);
switch( m.toLowerCase() ){
case 'post': p=params.join('&'); break;
case 'get': u+='?'+params.join('&'); p=null; break;
}
xhr.open( m.toUpperCase(), u, true );
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xhr.send( p );
}
function createmenu(r,o,h){
o.menu.innerHTML=r;
}
function bindEvents(){
var oSelItem2=document.querySelector('select[name="item2"]');
var oSelService2=document.querySelector('select[name="service2"]');
oSelItem2.onchange=function(e){
var method='post';
var url=location.href;
var params={
'action':'get_dependant_menu',
'id':this.options[ this.options.selectedIndex ].value
};
var opts={
menu:oSelService2
};
ajax.call( this, method, url, params, createmenu, opts );
}.bind( oSelItem2 );
}
document.addEventListener( 'DOMContentLoaded', bindEvents,false );
</script>
<script type='text/javascript' charset='utf-8'>
function ajax(m,u,p,c,o){
var xhr=new XMLHttpRequest();
xhr.onreadystatechange=function(){
if( xhr.readyState==4 && xhr.status==200 )c.call( this, xhr.response, o, xhr.getAllResponseHeaders() );
};
var params=[];
for( var n in p )params.push(n+'='+p[n]);
switch( m.toLowerCase() ){
case 'post': p=params.join('&'); break;
case 'get': u+='?'+params.join('&'); p=null; break;
}
xhr.open( m.toUpperCase(), u, true );
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xhr.send( p );
}
function createmenu(r,o,h){
o.menu.innerHTML=r;
}
function bindEvents(){
var oSelItem3=document.querySelector('select[name="item3"]');
var oSelService3=document.querySelector('select[name="service3"]');
oSelItem3.onchange=function(e){
var method='post';
var url=location.href;
var params={
'action':'get_dependant_menu',
'id':this.options[ this.options.selectedIndex ].value
};
var opts={
menu:oSelService3
};
ajax.call( this, method, url, params, createmenu, opts );
}.bind( oSelItem3 );
}
document.addEventListener( 'DOMContentLoaded', bindEvents,false );
</script>
</body>
</html>
最佳答案
在上面的代码中,您运行相同的查询两次,我认为这是复制/粘贴错误?
以下内容基于之前的问题和已提供的帮助。
mysql> describe irn_item;
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| irn | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(50) | YES | | NULL | |
+-------+------------------+------+-----+---------+----------------+
mysql> select * from irn_item;
+-----+------------+
| irn | name |
+-----+------------+
| 1 | Shirt |
| 2 | Trousers |
| 3 | Jacket |
| 4 | Socks |
| 5 | Underpants |
| 6 | Hat |
+-----+------------+
mysql> describe irn_service;
+-------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+----------------+
| srn | int(10) unsigned | NO | PRI | NULL | auto_increment |
| irn | int(10) unsigned | NO | MUL | 1 | |
| instruction | varchar(50) | NO | | 1 | |
+-------------+------------------+------+-----+---------+----------------+
mysql> select * from irn_service;
+-----+-----+-----------------------+
| srn | irn | instruction |
+-----+-----+-----------------------+
| 1 | 2 | Iron |
| 2 | 1 | Dry Clean Only |
| 3 | 3 | Hi-Pressure dry clean |
| 4 | 4 | Steam Clean |
| 5 | 5 | Decontaminate |
| 6 | 6 | Waterproof |
+-----+-----+-----------------------+
在不知道数据库架构的情况下,我根据原始代码中 sql 中看到的一些列创建了一个快速示例数据库。下面的代码使用 mysqli
而不是 PDO,只是因为对于我的测试来说,编写起来要快得多,所以请忽略它不完全遵循的事实。我认为,您遇到麻烦的重要方面是新添加的行不会复制触发 ajax 请求的事件处理程序。我昨天确实提到过,在克隆节点时,使用 addEventListener
分配的任何事件处理程序不会被复制/克隆 - 因此为了确保事件处理程序被复制/克隆,您需要使用 inline event handlers
〜即:<select onchange='evtselect(event)'>...</select>
<?php
$dbhost = 'localhost';
$dbuser = 'root';
$dbpwd = 'xxx';
$dbname = 'xxx';
$db = new mysqli( $dbhost, $dbuser, $dbpwd, $dbname );
if( $_SERVER['REQUEST_METHOD']=='POST' && isset( $_POST['action'], $_POST['id'] ) && $_POST['action']=='get_dependant_menu' ){
ob_clean();
try{
$id=filter_input( INPUT_POST, 'id', FILTER_SANITIZE_STRING );
if( $id && !empty( $id ) ){
$html=array();
$sql='select `srn`,`instruction` from `irn_service` where `irn` = ? order by `srn` asc';
$stmt=$db->prepare( $sql );
if( $stmt ){
$stmt->bind_param( 's', $id );
$stmt->execute();
$stmt->store_result();
$stmt->bind_result( $srn, $instruction );
while( $stmt->fetch() ){
$html[]="<option value='{$srn}'>{$instruction}";
}
$stmt->close();
}
header('Content-Type: text/html');
echo implode( PHP_EOL, $html );
}
}catch( Exception $e ){
echo $e->getMessage();
}
exit();
}
?>
<!doctype html>
<html>
<head>
<title>Dependent / Chained SELECT menus</title>
<script>
/* AJAX FUNCTION */
function ajax(m,u,p,c,o){
var xhr=new XMLHttpRequest();
xhr.onreadystatechange=function(){
if( xhr.readyState==4 && xhr.status==200 )c.call( this, xhr.response, o, xhr.getAllResponseHeaders() );
};
var params=[];
for( var n in p )params.push(n+'='+p[n]);
switch( m.toLowerCase() ){
case 'post': p=params.join('&'); break;
case 'get': u+='?'+params.join('&'); p=null; break;
}
xhr.open( m.toUpperCase(), u, true );
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xhr.send( p );
}
/* AJAX CALLBACK */
function createmenu(r,o,h){
o.menu.innerHTML=r;
}
/* UTILITY TO FIND NEXT SIBLING ELEMENT NODE */
function get_nextsibling(n){
x=n.nextSibling;
while ( x.nodeType!==1 ) x=x.nextSibling;
return x;
}
/* INLINE EVENT HANDLER */
function evtselect(e){
try{
var el=e.target;
if( el.value=='null' || el.value==null )return false;
var method='post';
var url=location.href;
var params={
'action':'get_dependant_menu',
'id':el.value
};
var td=get_nextsibling( el.parentNode );
var oSelect=td.querySelector('select');
var opts={
menu:oSelect
};
ajax.call( this, method, url, params, createmenu, opts );
}catch( err ){
console.log( err );
}
}
function bindEvents(){
var bttn=document.querySelector('input[name="add"]');
var tbl=document.querySelector('form#item_sel > table');
if( bttn && tbl ){
bttn.addEventListener('click',function(e){
/* get a reference to the first & last row, of class "item", in table */
var tr=tbl.querySelectorAll( 'tr.items' )[0];
var ref=tbl.querySelector( 'tr.save' );
/* Create a clone of the entire row - which includes the inline event handlers */
var clone=tr.cloneNode( true );
/* Insert the new row after the last row */
tr.parentNode.insertBefore( clone, ref );
/* Ensure that newly added "service" select menu is empty */
clone.querySelector('select[name="item[]"]').value='null';
clone.querySelector('select[name="service[]"]').innerHTML='';
clone.querySelector('input[name="qty[]"]').value='';
},{ capture:false, passive:true, once:false } );
}
}
document.addEventListener( 'DOMContentLoaded', bindEvents, false );
</script>
<style type='text/css' charset='utf-8'>
select {padding:1rem;width:300px;}
</style>
</head>
<body>
<h1>Chained select menus using basic ajax</h1>
<form method='post' id='item_sel'>
<table>
<tr class='headers'>
<th scope='col'>Item</th>
<th scope='col'>Service</th>
<th scope='col'>Qty</th>
</tr>
<tr class='items'>
<td>
<select name='item' class='country' onchange='evtselect(event)'>
<option value=null>Please Select
<?php
$sql='select * from `irn_item` order by `irn`;';
$result=$db->query( $sql );
$html=array();
if( $result ){
while( $rs=$result->fetch_object() ){
$html[]="<option value='{$rs->irn}'>{$rs->name}";
}
echo implode( PHP_EOL, $html );
}
?>
</select>
</td>
<td><select name='service' class='country'></select></td>
<td><input type='number' name='qty' min=0 max=1000 /></td>
</tr>
<tr class='save'>
<td colspan='3'>
<button type='submit' name='btnsave' class='btn btn-default'>
<span class='glyphicon glyphicon-save'></span> Save
</button>
</td>
</tr>
</table>
<input name='add' type='button' class='add-row' value='Add Row' />
</form>
</body>
</html>
使用此代码,我不厌其烦地重命名了新添加的元素 - 这可能并不是绝对必要的,因为您可以改为使用 array syntax
对于元素名称 - 即:<select name='item[]' onchange='evtselect(event)>
或<input type='number' name='qty[]' />
等然后以通常的方式访问 PHP 中的适当值。应该提到的是,如果您决定采用这种方法(即数组语法),那么您将需要查看 JavaScript 中使用的各种选择器并适本地编辑名称。
我相信有了对 inline event handlers
的使用的新见解您应该能够解决您遇到的问题 - 您可以通过对此代码进行一些小的编辑,自己运行它以查看应用程序是否正常工作。您应该编辑表名称( irn_item
-> item
、 irn_service
-> service
)并添加合适的 db/pwd 详细信息...祝你好运
关于javascript - 基于使用 php 的另一个选择进行选择不工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47321918/