0

I have been searching solutions for this and found that the most effective way is through a hacky workaround like this, but none of them has posted a working way to catching every tick and untick box for a dynamic input row using a lot of checkbox arrays.

I looked around and saw a script way -- let hidden inputs be the POST source and change value according to their adjacent checkbox upon submit. However the jquery doesn't seem to work -- it always submits a value of 0 (whatever the value attribute inside hidden inputs.

$(document).ready(function() {
  $('#frm').submit(function() {
    $('input[type="checkbox"]:checked').prev('.checkboxHandler').val(1);
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<input type="hidden" class="checkboxHandler" name="isHeadOfFamily[]" value="0">
<td><input type="checkbox"></td>
<input type="hidden" class="checkboxHandler" name="isEmployed[]" value="0">
<td><input type="checkbox"></td>
<! and so on-->
  • Your code works – mplungjan Oct 12 '21 at 13:56
  • It is not clear why you are storing `0` or `1` in a hidden text field. Why not use the `checked` property state of the checkbox? It's providing the same `true` or `false` binary response. – Twisty Oct 12 '21 at 14:20
  • i need to store the values of 0 and 1 in sql. unfortunately unticked boxes will not POST anything and trying to set it on PHP causes misplaced arrays – inNeedOfHelp Oct 12 '21 at 14:29
  • @inNeedOfHelp you can iterate each of them and build your own form data. Using a tertiary operator for this: `isHeadOfHouse.push(($(el).prop("checked") ? 1 : 0));` for example. Remember if you send a binary variable to PHP and to SQL, it will address it as such. – Twisty Oct 12 '21 at 14:35
  • @Twisty It can be any value like "true" so "1" makes just as much sense. The server will have to parse the result regardless. Why are you discussing binary values? and `isHeadOfHouse` is a field name, not a client side array – mplungjan Oct 12 '21 at 14:54

2 Answers2

0

Your code works

I will delete this answer once we have discussed it

I have changed hidden to text and added preventDefault to show it works

$(document).ready(function() {
  $('#frm').on("submit",function(e) {
    e.preventDefault(); //while testing
    $('input[type="checkbox"]:checked').prev('.checkboxHandler').val(1);
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<form id="frm">
<input type="text" class="checkboxHandler" name="isHeadOfFamily[]" value="0">
<td><input type="checkbox"></td>
<input type="text" class="checkboxHandler" name="isEmployed[]" value="0">
<td><input type="checkbox"></td>
<! and so on-->
<input type="submit"/>
</form>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • Strange. It still doesnt work for me, they still dont change the text values. However, I could change the value attribute of the hidden input, and it would successfully submit to SQL to whatsever in it. My PHP for these checkboxes is just the same as the rest of the other fields and they submit properly, so I wonder what could be the source of the problem for this one. – inNeedOfHelp Oct 12 '21 at 14:46
  • I cannot tell. Perhaps point the form to a simple form echo script – mplungjan Oct 12 '21 at 14:55
0

Consider the following example.

$(function() {
  function getTableData(table) {
    var results = [];
    $("tbody > tr", table).each(function(i, row) {
      results.push({
        id: $(row).data("uid"),
        isHeadofHousehold: $("input", row).eq(0).prop("checked"),
        isEmployed: $("input", row).eq(1).prop("checked")
      });
    });
    return results;
  }
  $('#frm').on("submit", function(e) {
    e.preventDefault();
    var formData = getTableData($("#myTable"));
    console.log(formData);
  });
});
.checkbox {
  text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<form id="frm">
  <table id="myTable">
    <thead>
      <tr>
        <th>Name</th>
        <th>Head of Household</th>
        <th>Employed</th>
      </tr>
    </thead>
    <tbody>
      <tr data-uid="1001">
        <td>Homer Simpson</td>
        <td class="checkbox"><input type="checkbox" name="isHeadOfFamily[]" checked></td>
        <td class="checkbox"><input type="checkbox" name="isEmployed[]" checked></td>
      </tr>
      <tr data-uid="1002">
        <td>Marge Simpson</td>
        <td class="checkbox"><input type="checkbox" name="isHeadOfFamily[]"></td>
        <td class="checkbox"><input type="checkbox" name="isEmployed[]"></td>
      </tr>
    </tbody>
  </table>
  <input type="submit" value="Save" />
</form>

You now have:

[
  {
    "id": 1001,
    "isHeadofHousehold": true,
    "isEmployed": true
  },
  {
    "id": 1002,
    "isHeadofHousehold": false,
    "isEmployed": false
  }
]

You can then use AJAX to POST this data back to PHP so the changes can be saved to SQL. As mentioned, you can switch them to 1 and 0 respectively if you choose.

Update

Returning to OP's desired method, consider the following.

$(function() {
  $("#frm").on("change", "input[type='checkbox']", function(event) {
    $(this).prev(".checkboxHandler").val($(this).prop("checked") ? 1 : 0);
  });
});
.checkbox {
  text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<form id="frm">
  <table id="myTable">
    <thead>
      <tr>
        <th>Name</th>
        <th>Head of Household</th>
        <th>Employed</th>
      </tr>
    </thead>
    <tbody>
      <tr data-uid="1001">
        <td>Homer Simpson</td>
        <td class="checkbox">
          <input type="hidden" class="checkboxHandler" name="isHeadOfFamily[]" value="1" />
          <input type="checkbox" checked />
        </td>
        <td class="checkbox">
          <input type="hidden" class="checkboxHandler" name="isEmployed[]" value="1" />
          <input type="checkbox" checked />
        </td>
      </tr>
      <tr data-uid="1002">
        <td>Marge Simpson</td>
        <td class="checkbox">
          <input type="hidden" class="checkboxHandler" name="isHeadOfFamily[]" value="0" />
          <input type="checkbox" />
        </td>
        <td class="checkbox">
          <input type="hidden" class="checkboxHandler" name="isEmployed[]" value="0" />
          <input type="checkbox" />
        </td>
      </tr>
    </tbody>
  </table>
  <input type="submit" value="Save" />
</form>

This updates the hidden text box value when a User makes a change.

If you are insistent on using the original code, use the following:

$('input[type="checkbox"]:checked').prevAll('.checkboxHandler').val(1);

I strongly advise not using this, as it's a one way logic and if the User unchecks a box before the form is submitted, the change will not be captured.

Update 2

Based on the Top rated answer here, you could also do this:

<td>
  <input type="hidden" name="isHeadOfFamily[]" value="0">
  <input type="checkbox" name="isHeadOfFamily[]" value="1">
</td>
<td>
  <input type="hidden" name="isEmployed[]" value="0">
  <input type="checkbox" name="isEmployed[]" value="1">
</td>

The only caveat is that if the User checks a box, both values would get sent. So as suggested, disable the hidden upon submit if unchecked.

$("#frm").submit(function(){
  $('input[type="checkbox"]:checked').prevAll().prop("disabled", true);
});
Twisty
  • 30,304
  • 2
  • 26
  • 45
  • Why not just serialize the form? – mplungjan Oct 12 '21 at 15:52
  • @mplungjan that would totally work too. It all depends on what OP needs to send back to the server or how the data is presented in the HTML. – Twisty Oct 12 '21 at 16:27
  • But actually his existing code SHOULD work, without all this so he needs to see why it does not – mplungjan Oct 12 '21 at 17:33
  • @mplungjan I do agree that OP's existing code *should work*. I think maybe it needs to iterate each element, so there is a proper relationship for `.prev()` to identify the element. If there were 7 "rows", the original selector would have up to 7 potential elements. *To select all preceding sibling elements, rather than just the preceding adjacent sibling, use the `.prevAll()` method.* – Twisty Oct 12 '21 at 19:18
  • @mplungjan I have updated my answer to reflect more options. – Twisty Oct 12 '21 at 19:36
  • $(this).prev(".checkboxHandler").val($(this).prop("checked") ? 1 : 0); this doesn't work, mine either, and I dont know how. I changed the hiddens into texts to see but they wont change value from default. I even put alerts before and after that code -- they do send their alerts, but this code doesnt reflect anything. – inNeedOfHelp Oct 13 '21 at 04:34
  • Which is weird, considering the thread answers from [here](https://stackoverflow.com/questions/1809494/post-unchecked-html-checkboxes) use the exact or variations of this code and posted it as solution – inNeedOfHelp Oct 13 '21 at 04:40
  • @inNeedOfHelp the Top rated answer you referred to does not use any JS. It just has a hidden element with a 0 value, but with the sane Name. So when the form is Posted, the value is passed even if the checkbox is unchecked. If your code is not working, but some is, this would suggest it's not being read or there is a Stop error after some of the code. Please check your console for any errors. Also ensure that all of your Libraries are loading properly. – Twisty Oct 13 '21 at 14:23