Select based on another select using php Not working

匿名 (未验证) 提交于 2019-12-03 09:06:55

问题:

Select based on another select using PHP not working only when a new row is added.

For demo visit here (See steps for demo)

  1. There are two rows when the page is loaded, they are working as wanted. (Service option is as per item option)
  2. Click on the Add Row button, one more row will be added
  3. The newly inserted row is not working. (Service select is not giving any options, as first two gives)

What I tried:

<?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> &nbsp; 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> 

回答1:

In your code above you are running the same query twice which I presume is a copy/paste mistake?

What follows is based upon previous question and help already offered.

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            | +-----+-----+-----------------------+ 

Without knowing the schema of the database I made up a quick example database based upon some of the columns seen in the sql in the original code. The code below uses mysqli rather than PDO simply because for my testing it is much quicker to write so please ignore the fact that it does not follow exactly. The important aspect that you are having troubles with, I believe, is that newly added rows do not copy the event handler which triggers the ajax request. I did make mention yesterday that when cloning nodes any event handlers assigned using addEventListener will NOT be copied/cloned - so to ensure that event handlers are copied/cloned you need to use inline event handlers ~ ie: <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> &nbsp; Save                         </button>                     </td>                 </tr>             </table>             <input name='add' type='button' class='add-row' value='Add Row' />         </form>     </body> </html> 

With this code I took the trouble of renaming newly added elements - this is probably not strictly necessary as you could instead use array syntax for the element names - viz: <select name='item[]' onchange='evtselect(event)> or <input type='number' name='qty[]' /> etc then access the appropriate values in PHP in the usual manner. It should be mentioned that if you decide upon that approach (ie array syntax ) then you would need to look at the various selectors used in the javascript and edit the names appropriately.

I trust that with this new insight into the use of inline event handlers that you should be able to nail the problem you have - you can, with a little minor editing of this code, run it for yourself to see the application working correctly. You should edit the table names (irn_item -> item, irn_service -> service ) and add suitable db/pwd details... Good luck



回答2:

You've really to change the logic here, I'm sorry but dealing with dynamic content statically will not work in this case... what if we have line 4 and 5 and 10.. you need really to give all set of elements a common class then attach the event using the event delegation on() so the new elements added dynamically will also binded.

Example, change country class to item in the item columns, and country class to service in the service column :

$('body').on('change', '.item', function(){    //You're ajax logic here    //Try to use `$.post()` instead     //Target the related service list like    var related_service_select = $(this).closest('tr').find('.service');    //Now you can fill it with the server side response }); 

Hope this helps.



回答3:

Your problem is because of this error - Uncaught TypeError: Cannot set property 'onchange' of null at HTMLDocument.bindEvents on line 243. You can see the same in inspect elements. This is because you are defining the function bindEvents for item3, which has not yet been added. Also this will work only in case of a single row being added. Changed your logic and used jquery a lot. I have commented out php part in your code and hard coded that stuff. Also created a php file that sends ajax response on select box change.

    <?php // require_once '../home.php' ?>     <?php      foreach($_POST as $key => $val) {         echo "$key => $val <br>";     }          if( $_SERVER['REQUEST_METHOD']=='POST' && isset( $_POST['action'], $_POST['id'] ) && $_POST['action']=='get_dependant_menu' ){             echo "here <br>";             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>";     //                 }     //            }     //        }             echo "<option value='Select Service'>Select Service (Pant)</option>";             echo "<option value='12121211'>Iron</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>      </head>     <body>         <div class="container">     <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>";     //                    }     //                }                  ?>                              <option value='ZZ2017TF11A1'>Shirt</option>                             <option value='ZZ2017TF11A2'>Pant</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>";     //                    }     //                }                  ?>                              <option value='ZZ2017TF11A1'>Shirt</option>                             <option value='ZZ2017TF11A2'>Pant</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> &nbsp; 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>";     //                            }     //                        }                            ?>                              <option value='ZZ2017TF11A1'>Shirt</option>                             <option value='ZZ2017TF11A2'>Pant</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="js/jquery-2.1.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++;       });           $('.container').on( 'change', '.country', function () {             //console.log($(this).attr('name'));             var oSelItem = $(this).attr('name');             var lastChar = oSelItem.substr(oSelItem.length -1);              var prevChar = oSelItem.substr(0, oSelItem.length-1);             //console.log(prevChar);             if(prevChar === "item") {               var oSelService = "service" + lastChar;               console.log(oSelItem + "  " + oSelService);                console.log($(this).val());               var thisId = $(this).val();               $.ajax({                 type: 'post',                 url: 'ajax.php',                 data: {                  'id':thisId,                  'action':'get_dependent_menu'                 },                 success: function (response) {                 //alert(response);                  console.log(oSelService);                 $('select[name="'+ oSelService +'"]').html(response);                  }              });                       }          });       });     </script>       </body>     </html> 

And ajax.php

    <?php     echo "<option value='Select Service'>Select Service (Pant)</option>";     echo "<option value='12121211'>Iron</option>";      ?> 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!