skip to Main Content

I have a form that is displayed in a table. This table has some elements and javascript which allows the template row to be duplicated to allow the user to add/remove rows as they want.

Here is a simplified version of the template

<tr data-being_removed="false" data-type="pickup" id="stop_table_row_template" style="display: none;">
    <td>
        <div class="input-group" style="margin: 0px;">
            <input type="text" placeholder="Pickup Number" class="form-control form-control-sm" name="stops[stop_number][]">
            <div class="input-group-text">
                <input class="form-check-input mt-0" name="stops[require_appointment][]" type="checkbox" value="1">
                &nbsp;Req. Appt.
            </div>
        </div>
        <select placeholder="Location" class="form-select ship_to_selector form-control-sm mt-1" name="stops[location_id][]">
            <option value="">Location</option>
        </select>
    </td>
</tr>

However, checkboxes are not sent to the server if they are not checked. Usually to get around this I would create a hidden input with an identical name. However, in this case, that would cause the actual checkbox to be associated to the wrong row because the hidden input will ALWAYS be sent but the checkboxes will also SOMETIMES be sent, throwing off the implied indexes.

In the current code, it does not work for the opposite reason. For example, if the user has 3 rows, but the checkbox is only checked on the 2nd row, the form thinks the checkbox belongs to the first row because there is no matching name attribute sent to the server from the first row.

I would like to avoid having to specify indexes in the name attributes themselves. Is there any way I can send a "0" value for the name of the checkbox if the one with "1" value is not checked?

2

Answers


  1. Chosen as BEST ANSWER

    What I ended up doing was adding a hidden input field which has the name attribute associated with my checkbox, and removed the name attribute from the checkbox itself.

    <div class="input-group-text">
        <input class="form-check-input mt-0 req_appt" name="stops[require_appointment][]" type="hidden" value="0" disabled>
        <input class="form-check-input mt-0 req_appt_checkbox" type="checkbox">
        &nbsp;Req. Appt.
    </div>
    

    Then, when the checkbox is changed, it updates the hidden input.

    $(document).on('change', '.req_appt_checkbox', function() {
        let e = $(this);
        e.closest('div').find('.req_appt').val(e.is(':checked') ? 1 : 0);
    });
    

  2. One solution that I have below is to loop through the checkboxes and just convert the unchecked ones to type hidden. Or you could always convert them all to hidden.

    This way, there aren’t a mismatch of field counts.

    const send = document.querySelector(".send");
    
    send.addEventListener("click",(e) => {
        let fields = document.querySelectorAll("input[type='checkbox']:not(:checked)");
        fields.forEach((f) => f.type = "hidden");
    });
    <table>
    <tr data-being_removed="false" data-type="pickup" id="stop_table_row_template">
        <td>
            <div class="input-group" style="margin: 0px;">
                <input type="text" placeholder="Pickup Number" class="form-control form-control-sm" name="stops[stop_number][]">
                <div class="input-group-text">
                    <input class="form-check-input mt-0" name="stops[require_appointment][]" type="checkbox" value="1">
                    &nbsp;Req. Appt.
                </div>
            </div>
            <select placeholder="Location" class="form-select ship_to_selector form-control-sm mt-1" name="stops[location_id][]">
                <option value="">Location</option>
                <option value="x">Locationx</option>
            </select>
        </td>
    </tr>
    </table>
    <button class="send">SEND</button>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search