Home > Net >  Select Items not showing after form appends
Select Items not showing after form appends

Time:08-08

The Select Items in my code below works if I havent added a new row yet. The items are fetched from a db using php mysql. How Can I still make the select options in the children elements work like the parent element cloned. The select button works like its disabled in the children element I want the children element to also have the room to select items

<script type="text/javascript">
    function create_tr(table_id) {
    let table_body = document.getElementById(table_id),
        first_tr = table_body.firstElementChild
    tr_clone = first_tr.cloneNode(true);

    table_body.append(tr_clone);

    clean_first_tr(table_body.firstElementChild);
}

function clean_first_tr(firstTr) {
    let children = firstTr.children;

    children = Array.isArray(children) ? children : Object.values(children);
    children.forEach(x => {
        if (x !== firstTr.lastElementChild) {
            x.firstElementChild.value = '';
        }
    });
}



function remove_tr(This) {
    if (This.closest('tbody').childElementCount == 1) {
        alert("First Row Can't Be Deleted");
    } else {
        This.closest('tr').remove();
    }
}
</script>
<div >
  <div >
    <div >
      <h3 >Add Device Information</h3>
    </div>
    <div >
      <form id="" method="POST" autocomplete="off" novalidate="novalidate">
        <table >
          <thead>
            <tr>
              <th>Device Model</th>
              <th>Serial No</th>
              <th>
                <button type="button" id="add"  onclick="create_tr('table_body')">
                  <i  id="add" style="font-size:1.6em;"></i>
                </button>
              </th>
            </tr>
          </thead>
          <tbody  id="table_body">
            <tr>
              <td>
                <select  data-bs-placeholder="Select" name="model[]" required="" id="model"> <?php 
                                $readALL1 = "SELECT * FROM productmodels WHERE deleted = 0";
                                $displayAll1 = mysqli_query($conn,$readALL1);
                                while($rowFetchAll1 = mysqli_fetch_array($displayAll1)){
                                    $modelName = $rowFetchAll1['modelName'];
                                    $modelid = $rowFetchAll1['modelID'];
                              ?> <option value="
                                        <?=$modelid?>"> <?=$modelName?> </option> <?php } ?> </select>
              </td>
              <td>
                <input type="" name=""  placeholder="Serial No...">
                <input type="text" name="addedBy[]"  id="addedBy" value="
                                        <?=$_SESSION['user_uniq_id']?>" hidden="">
                <input type="text" name="client[]"  value="
                                            <?=$clientID?>" id="client" hidden="">
                <input type="text" name="deviceID[]"  value="
                                                <?=time()?>" id="deviceID" hidden="">
              </td>
              <td>
                <button type="button" id="add"  onclick="remove_tr(this)">
                  <i  id="add" style="font-size:1.6em;"></i>
                </button>
              </td>
            </tr>
          </tbody>
        </table>
      </form>
    </div>
  </div>
</div>

CodePudding user response:

As per the comment I made above, you have duplicate IDs so whenever you use document.getElementByID you are going to have issues if attempting to call an element that has it's ID duplicated.

Fo the delete buttons to work you can either assign the event handler explicitly when you make the clone of the entire table row or the preferred method is to use a delegated event handler that intercepts click events to the common parent ( the table is easy ) and then reacts accordingly. The following HTML is a modified version of the above - all IDs have been removed, some replaced with dataset attributes. The select menu simply has a basic statically written few options to illustrate the case.

// No element in the HTML now has an ID so there will be no duplicate IDs. To identify
// DOM elements a more useful set of selectors (querySelector & querySelectorAll) are
// very useful. The `event` can be used to begin DOM traversal to find elements of 
// interest rather than rely upon a static ID or crudely constructed dynamic IDs, usually
// involving numbers.
document.querySelector('button[data-name="add"]').addEventListener('click', e => {
  // from the event.target, find the parent table row and from that the table-body
  let tbody = e.target.closest('table').querySelector('tbody');
  // clone the first row from table-body and do some manipulations
  let clone=tbody.firstElementChild.cloneNode(true);
      clone.querySelector('button[data-name="del"]').hidden=false;
      clone.querySelectorAll('input, select').forEach(n=>{
        n.value='';
      });
  // add the new row - no IDS anywhere.
  tbody.appendChild(clone);
  
});

// Delegated Event Listener. This is bound to the table and monitors `click` events
// but processes only those events originating from the specified elements (button & i)
// - newly added elements are not registered in the DOM when the page loads initially
// which is why a delegated listener is used.
document.querySelector('form table#dyntbl').addEventListener('click', e => {
  e.stopPropagation();
  // only process clicks from either a button with dataset.name='del' or it's child i
  if (e.target != e.currentTarget && (e.target.dataset.name == 'del' || e.target.parentNode.dataset.name == 'del')) {
    // identify the table-body as before
    let tbody = e.target.closest('table').querySelector('tbody');
    // remove table row unless it is the 1st one otherwise things break.
    if( tbody.childNodes.length > 3 ) tbody.removeChild(e.target.closest('tr') )
    
  }
});
<div class='col-xl-8 col-md-12'>
  <div class='card'>
    <div class='card-header'>
      <h3 class='card-title'>Add Device Information</h3>
    </div>
    <div class='card-body'>
      <form method='POST' autocomplete='off' novalidate='novalidate'>
        <table id='dyntbl' class='table border text-nowrap text-md-nowrap table-striped mb-0'>
          <thead>
            <tr>
              <th>Device Model</th>
              <th>Serial No</th>
              <th>
                <button type='button' data-name='add' class=' btn text-success'>
                    <i class='fe fe-plus-circle' data-id='add' style='font-size:1.6em;'>#Add#</i>
                </button>
              </th>
            </tr>
          </thead>
          <tbody class='field_wrapper'>
            <tr>
              <td>
                <select class='form-control form-select select2' data-bs-placeholder='Select' name='model[]' required>
                  <option>A
                  <option>B
                  <option>C
                </select>
              </td>
              <td>
                <input type='text' name='serial[]' class='form-control' placeholder='Serial No...' />
                <input type='text' name='addedBy[]' class='form-control' hidden />
                <input type='text' name='client[]' class='form-control' hidden />
                <input type='text' name='deviceID[]' class='form-control' hidden />
              </td>
              <td>
                <button type='button' data-name='del' class='btn text-danger' hidden>
                   <i class='fe fe-minus-circle' style='font-size:1.6em;'>#Delete#</i>
                </button>
              </td>
            </tr>
          </tbody>
        </table>
      </form>
    </div>
  </div>
</div>

  • Related