Home > Software engineering >  How to select only one row in table with checkbox
How to select only one row in table with checkbox

Time:10-14

I have a table with x numbers of rows and 4 columns, one column is checkbox and other three are readonly selectboxs. I want the user to select just 1 row to be editable by checking checkbox in first column then if he check another checkbox in another row, the checkbox he previously checked get unchecked and row get readonly again.

So I want the user to select 1 row only to edit and others be readonly. here is my code but it is not working.

$(document).ready(function(){
  $('.col1, .col2, .col3').attr('disabled', true)
   selectRow();
    $('.tbl').on('change', '.selectRow', selectRow);
    function selectRow() {
     $('.tbl tbody tr').each(function () {
     $(this).find('.selectRow').each(function () {
      var checkedRow = $(this).closest('tr').find('input:checkbox:checked'),
        col1 = $(this).closest('tr').find('.col1'),
        col2 = $(this).closest('tr').find('.col2'),
        col3 = $(this).closest('tr').find('col3');
        if (checkedRow){
        $('.col1, .col2, .col3').removeAttr('disabled')
    checkedRow.siblings().prop('checked', false);
    }else{
        $('.col1, .col2, .col3').attr('disabled', true)
    checkedRow.siblings().prop('checked', false);
    }
 });
});
}
});
<table class="tbl">
<tr>
  <td><input type="checkbox" name="check1" class = "selectRow" />&nbsp;</td>
  <td>
   <select class="col1">
       <option id="col1o1">A</option>
       <option id="col1o2">B</option>
       <option id="col1o3">C</option>
       <option id="col1o4">E</option>
   </select>
  </td>
    <td>
   <select class="col2">
       <option id="col2o1">A</option>
       <option id="col2o2">B</option>
       <option id="col2o3">C</option>
       <option id="col2o4">E</option>
   </select>
  </td>
    <td>
   <select class="col3">
       <option id="col3o1">A</option>
       <option id="col3o2">B</option>
       <option id="col3o3">C</option>
       <option id="col3o4">E</option>
   </select>
  </td>
</tr>
<br>
<tr>
  <td><input type="checkbox" name="check1" />&nbsp;</td>
  <td>
   <select class="s1">
       <option id="s1o1">A</option>
       <option id="o2">B</option>
       <option id="o3">C</option>
       <option id="o4">E</option>
   </select>
  </td>
    <td>
   <select class="s2">
       <option id="s2o1">A</option>
       <option id="s2o2">B</option>
       <option id="s2o3">C</option>
       <option id="s2o4">E</option>
   </select>
  </td>
    <td>
   <select class="s3">
       <option id="s3o1">A</option>
       <option id="s3o2">B</option>
       <option id="s3o3">C</option>
       <option id="s3o4">E</option>
   </select>
  </td>
</tr>
<br>
<tr>
  <td><input type="checkbox" name="check1" />&nbsp;</td>
  <td>
   <select class="s1">
       <option id="s1o1">A</option>
       <option id="o2">B</option>
       <option id="o3">C</option>
       <option id="o4">E</option>
   </select>
  </td>
    <td>
   <select class="s2">
       <option id="s2o1">A</option>
       <option id="s2o2">B</option>
       <option id="s2o3">C</option>
       <option id="s2o4">E</option>
   </select>
  </td>
    <td>
   <select class="s3">
       <option id="s3o1">A</option>
       <option id="s3o2">B</option>
       <option id="s3o3">C</option>
       <option id="s3o4">E</option>
   </select>
  </td>
</tr>
</table>

this is my code:

CodePudding user response:

Without jQuery and using event delegation things may be somewhat simpler:

document.addEventListener(`click`, handle);

// disable all selectors initially
document.querySelectorAll(`td select`)
  .forEach(s => s.setAttribute(`disabled`, true));

function handle(evt) {
  // only do something if a checkbox was clicked
  if (evt.target.type === `checkbox`) {
    const isChecked = evt.target.checked;
    const selectedRow = evt.target.closest(`tr`);
    // reset checkboxes, row coloring and disabled state
    document.querySelectorAll(`input[type='checkbox']`)
      .forEach(cb => {
        cb.checked = cb !== evt.target ? false : isChecked;
        const row = cb.closest(`tr`);
        row.classList[isChecked && row === selectedRow ?
          `add` : `remove`](`selected`);
        [...row.querySelectorAll(`select`)].filter(r => r !== selectedRow)
          .forEach(s => s.setAttribute(`disabled`, true));
        selectedRow.querySelectorAll(`select`)
          .forEach(s => s[isChecked ? 
              `removeAttribute` : `setAttribute`](`disabled`, true));
      });
  }
}
body {
  margin: 2rem;
}

tr.selected {
  background-color: lightgreen;
}
<table class="tbl">
  <tr>
    <td><input type="checkbox" name="check1" class="selectRow" />&nbsp;</td>
    <td>
      <select class="col1">
        <option id="col1o1">A</option>
        <option id="col1o2">B</option>
        <option id="col1o3">C</option>
        <option id="col1o4">E</option>
      </select>
    </td>
    <td>
      <select class="col2">
        <option id="col2o1">A</option>
        <option id="col2o2">B</option>
        <option id="col2o3">C</option>
        <option id="col2o4">E</option>
      </select>
    </td>
    <td>
      <select class="col3">
        <option id="col3o1">A</option>
        <option id="col3o2">B</option>
        <option id="col3o3">C</option>
        <option id="col3o4">E</option>
      </select>
    </td>
  </tr>
  <br>
  <tr>
    <td><input type="checkbox" name="check1" />&nbsp;</td>
    <td>
      <select class="s1">
        <option id="s1o1">A</option>
        <option id="o2">B</option>
        <option id="o3">C</option>
        <option id="o4">E</option>
      </select>
    </td>
    <td>
      <select class="s2">
        <option id="s2o1">A</option>
        <option id="s2o2">B</option>
        <option id="s2o3">C</option>
        <option id="s2o4">E</option>
      </select>
    </td>
    <td>
      <select class="s3">
        <option id="s3o1">A</option>
        <option id="s3o2">B</option>
        <option id="s3o3">C</option>
        <option id="s3o4">E</option>
      </select>
    </td>
  </tr>
  <br>
  <tr>
    <td><input type="checkbox" name="check1" />&nbsp;</td>
    <td>
      <select class="s1">
        <option id="s1o1">A</option>
        <option id="o2">B</option>
        <option id="o3">C</option>
        <option id="o4">E</option>
      </select>
    </td>
    <td>
      <select class="s2">
        <option id="s2o1">A</option>
        <option id="s2o2">B</option>
        <option id="s2o3">C</option>
        <option id="s2o4">E</option>
      </select>
    </td>
    <td>
      <select class="s3">
        <option id="s3o1">A</option>
        <option id="s3o2">B</option>
        <option id="s3o3">C</option>
        <option id="s3o4">E</option>
      </select>
    </td>
  </tr>
</table>

CodePudding user response:

The issue is because checkedRow holds a jQuery object. When you use that in an if condition it will always equate to true. You instead need to get the checked property from that element and use that in the condition instead.

Also note that the logic can be made much more succinct and extensible through the use of common selectors instead of incremental ones. In addition, you should look to add the disabled attribute to the HTML directly. Adding it via JS means that there will be a visible flash where the element is loaded as enabled, then when the DOM loads it will be disabled which is not good for your UX.

jQuery($ => {
  selectRow();
  $('.tbl').on('change', '.selectRow', selectRow);

  function selectRow() {
    $('.tbl tbody tr').each(function() {
      let $row = $(this);
      let $checkbox = $row.find('.selectRow');
      $row.find('select').prop('disabled', !$checkbox.prop('checked'));
    });
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="tbl">
  <tr>
    <td><input type="checkbox" name="check1" class="selectRow" />&nbsp;</td>
    <td>
      <select class="col1" disabled="disabled">
        <option id="col1o1">A</option>
        <option id="col1o2">B</option>
        <option id="col1o3">C</option>
        <option id="col1o4">E</option>
      </select>
    </td>
    <td>
      <select class="col2" disabled="disabled">
        <option id="col2o1">A</option>
        <option id="col2o2">B</option>
        <option id="col2o3">C</option>
        <option id="col2o4">E</option>
      </select>
    </td>
    <td>
      <select class="col3" disabled="disabled">
        <option id="col3o1">A</option>
        <option id="col3o2">B</option>
        <option id="col3o3">C</option>
        <option id="col3o4">E</option>
      </select>
    </td>
  </tr>
  <br>
  <tr>
    <td><input type="checkbox" name="check1" class="selectRow"  />&nbsp;</td>
    <td>
      <select class="s1">
        <option id="s1o1">A</option>
        <option id="o2">B</option>
        <option id="o3">C</option>
        <option id="o4">E</option>
      </select>
    </td>
    <td>
      <select class="s2">
        <option id="s2o1">A</option>
        <option id="s2o2">B</option>
        <option id="s2o3">C</option>
        <option id="s2o4">E</option>
      </select>
    </td>
    <td>
      <select class="s3">
        <option id="s3o1">A</option>
        <option id="s3o2">B</option>
        <option id="s3o3">C</option>
        <option id="s3o4">E</option>
      </select>
    </td>
  </tr>
  <br>
  <tr>
    <td><input type="checkbox" name="check1" class="selectRow"  />&nbsp;</td>
    <td>
      <select class="s1">
        <option id="s1o1">A</option>
        <option id="o2">B</option>
        <option id="o3">C</option>
        <option id="o4">E</option>
      </select>
    </td>
    <td>
      <select class="s2">
        <option id="s2o1">A</option>
        <option id="s2o2">B</option>
        <option id="s2o3">C</option>
        <option id="s2o4">E</option>
      </select>
    </td>
    <td>
      <select class="s3">
        <option id="s3o1">A</option>
        <option id="s3o2">B</option>
        <option id="s3o3">C</option>
        <option id="s3o4">E</option>
      </select>
    </td>
  </tr>
</table>

CodePudding user response:

This works great! uncheck all checkboxes except the one having current focus '.tbl [type="checkbox"]:not(:focus)' then manipulate the select boxes

$(document).ready(function(){
  $('.tbl [type="checkbox"]').on('click', function() {
    $('.tbl [type="checkbox"]:not(:focus)').prop('checked', false);
    $('.tbl select').attr('disabled', true);
    $(this).parent().parent().find('select').attr('disabled', !$(this).prop('checked'));
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="tbl">
<tr>
  <td><input type="checkbox" name="check1" class = "selectRow" />&nbsp;</td>
  <td>
   <select class="col1" disabled>
       <option id="col1o1">A</option>
       <option id="col1o2">B</option>
       <option id="col1o3">C</option>
       <option id="col1o4">E</option>
   </select>
  </td>
    <td>
   <select class="col2" disabled>
       <option id="col2o1">A</option>
       <option id="col2o2">B</option>
       <option id="col2o3">C</option>
       <option id="col2o4">E</option>
   </select>
  </td>
    <td>
   <select class="col3" disabled>
       <option id="col3o1">A</option>
       <option id="col3o2">B</option>
       <option id="col3o3">C</option>
       <option id="col3o4">E</option>
   </select>
  </td>
</tr>
<br>
<tr>
  <td><input type="checkbox" name="check1" />&nbsp;</td>
  <td>
   <select class="s1" disabled>
       <option id="s1o1">A</option>
       <option id="o2">B</option>
       <option id="o3">C</option>
       <option id="o4">E</option>
   </select>
  </td>
    <td>
   <select class="s2" disabled>
       <option id="s2o1">A</option>
       <option id="s2o2">B</option>
       <option id="s2o3">C</option>
       <option id="s2o4">E</option>
   </select>
  </td>
    <td>
   <select class="s3" disabled>
       <option id="s3o1">A</option>
       <option id="s3o2">B</option>
       <option id="s3o3">C</option>
       <option id="s3o4">E</option>
   </select>
  </td>
</tr>
<br>
<tr>
  <td><input type="checkbox" name="check1" />&nbsp;</td>
  <td>
   <select class="s1" disabled>
       <option id="s1o1">A</option>
       <option id="o2">B</option>
       <option id="o3">C</option>
       <option id="o4">E</option>
   </select>
  </td>
    <td>
   <select class="s2" disabled>
       <option id="s2o1">A</option>
       <option id="s2o2">B</option>
       <option id="s2o3">C</option>
       <option id="s2o4">E</option>
   </select>
  </td>
    <td>
   <select class="s3" disabled>
       <option id="s3o1">A</option>
       <option id="s3o2">B</option>
       <option id="s3o3">C</option>
       <option id="s3o4">E</option>
   </select>
  </td>
</tr>
</table>

  • Related