How to dynamically remove and add a 'parsley-multiple' constraint on a set of checkboxes

696 views Asked by At

Okay, I have a form that users submit that either requires, or doesn't require, they tick at least one email option in a list, depending on another checkbox.

I am using Parsley.js 2.8.2 (it's a little behind, I know)

<form method="POST" id="completeForm" action="/api/order/dispatch/{{ order.kOrder }}">
    <div class="alert alert-warning">
        <b>Instructions</b>
        <div class="form-check">
            <input type="checkbox" class="form-check-input" name="data[mail_order]" id="shipping" />
            <label class="form-check-label" for="shipping"><b>SHIPPING</b></label>
        </div>
        <div class="form-check">
            <input type="checkbox" class="form-check-input" name="data[collect]" id="collection" />
            <label class="form-check-label" for="collection"><b>COLLECTION</b></label>
        </div>
    </div>

    <label>Send Shipping Email to:</label>
    <div id="emailsList">
        <div class="form-check" style="margin-bottom: 0.5rem">
        
          <!-- THIS IS THE MULTIPLE I AM TRYING TO TOGGLE -->
          
          <input class="form-check-input billing" type="checkbox" data-parsley-multiple="selectOneEmail" data-parsley-mincheck="1" data-parsley-required data-parsley-error-message="Please choose at least one email address" id="send-contact-{{ list.contacts.order.billing.kContact }}" name="to_emails[{{ list.contacts.order.billing.kContact }}]"/>
          <label class="form-check-label" for="send-contact-{{ list.contacts.order.billing.kContact }}">
            <b>Billing: </b>{{ list.contacts.order.billing.firstname }} {{ list.contacts.order.billing.lastname }} &lt;{{ list.contacts.order.billing.email }}&gt;
          </label>
          <br/>
          <input class="form-check-input delivery" type="checkbox" data-parsley-multiple="selectOneEmail" id="send-contact-{{ list.contacts.order.delivery.kContact }}" name="to_emails[{{ list.contacts.order.delivery.kContact }}]"/>
          <label class="form-check-label" for="tracksend-contact-{{ list.contacts.order.delivery.kContact }}ingId">
            <b>Delivery: </b>{{ list.contacts.order.delivery.firstname }} {{ list.contacts.order.delivery.lastname }} &lt;{{ list.contacts.order.delivery.email }}&gt;
          </label>
        </div>
        
    </div>
 
    <button type=select>COMPLETE</button>
</form>

This is the form - I am trying to toggle the requirement to "Please choose at least one email address"

I am currently using this script:

$(document).ready(function () {  
    $("form#completeForm").on("click", "input[type=checkbox]#collection", CompleteOrder.ToggleCollection);
});
function ToggleCollection(event) {
    var el = $(event.target);
    var modal = el.closest("div.modal");
    var form = $("form#completeForm", modal);
    var Shipping = $("input#Shipping", modal);
    var enabled = el.prop("checked");
    
    var emailCheckBoxes = $("div#emailsList input[type=checkbox]", modal);
    
    //console.log("Collection", enabled, emailCheckBoxes);

    if(enabled) {
        FastShipping.prop("disabled", true);
        //emailCheckBoxes.prop("disabled", true);
        emailCheckBoxes.attr("required", false);

        $(emailCheckBoxes[0]).parsley().removeConstraint("mincheck");
        $(emailCheckBoxes[0]).parsley().removeConstraint("required");
        $(emailCheckBoxes[0]).parsley().removeError("errorMessage");

        emailCheckBoxes.each(function () {
            $(this).parsley().removeConstraint("multiple");
        });

        form.parsley().reset();
    } else {
        FastShipping.prop("disabled", false);
        //emailCheckBoxes.prop("disabled", false);
        emailCheckBoxes.prop("required", true);

        $(emailCheckBoxes[0]).parsley().addConstraint({ "mincheck": 1 });
        $(emailCheckBoxes[0]).parsley().addConstraint({ "required": true });
        $(emailCheckBoxes[0]).parsley().addError({ "errorMessage": "Please choose at least one email address" });

        emailCheckBoxes.each(function () {
            $(this).parsley().addConstraint({ "multiple": "selectOneEmail" });
        });
        
        form.parsley().reset();
    }
}

Simply, I want the requirement to be active when the COLLECTION checkbox is unchecked and disabled if the COLLECTION checkbox is checked.

The function seems to run with no errors but it doesn't remove the validation requirement. If I check the COLLECTION checkbox it still fails and asks "Please choose at least one email address" on the form.

I'm struggling due to parsley.js's rather minimal documentation and wondered if anyone else could shed any light on this. It's also worth noting that there are cases where the number of email address checkboxes is more than 2, so it needs to support an arbitrary list of checkbox elements in the #emailsList div.

Thanks

1

There are 1 answers

0
ikhvjs On

You are adding constraints in the Old way(Parsley 1.x). Also, you didn't read the documentation properly. For example, you didn't pass a proper object to addError().

Example below:

$("#collection").on("change", ToggleCollection);

$("#myModal").modal("show");

const modal = $("div.modal");
const emailCheckBoxes = $("div#emailsList input[type=checkbox]", modal);
const form = $("form#completeForm", modal);
form.parsley();

function ToggleCollection(event) {
  var el = $(event.target);
  var enabled = el.prop("checked");

  if (enabled) {
    $("form").parsley().destroy();

    emailCheckBoxes.first().removeAttr("data-parsley-mincheck");
    emailCheckBoxes.first().removeAttr("data-parsley-required");
    emailCheckBoxes.first().parsley().removeError("error1");
    emailCheckBoxes.prop("checked", false);
    emailCheckBoxes.attr("disabled", true);

    form.parsley();
  } else {
    emailCheckBoxes.first().attr("data-parsley-mincheck", "2");
    emailCheckBoxes.first().attr("data-parsley-required", true);
    emailCheckBoxes.first().parsley().addError("error1", {
      message: "Please choose at least one email address",
    });
    emailCheckBoxes.attr("disabled", false);

    form.parsley().reset();
  }
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link
      rel="stylesheet"
      href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
      integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
      crossorigin="anonymous"
    />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script
      src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
      integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
      crossorigin="anonymous"
    ></script>
    <script
      src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
      integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
      crossorigin="anonymous"
    ></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/parsley.js/2.8.2/parsley.min.js"></script>
  </head>
  <body>
    <div id="myModal" class="modal" tabindex="-1" role="dialog">
      <div class="modal-dialog" role="document">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title">Modal title</h5>
            <button
              type="button"
              class="close"
              data-dismiss="modal"
              aria-label="Close"
            >
              <span aria-hidden="true">&times;</span>
            </button>
          </div>
          <div class="modal-body">
            <form
              method="POST"
              id="completeForm"
              action="/api/order/dispatch/{{ order.kOrder }}"
            >
              <div class="alert alert-warning">
                <b>Instructions</b>
                <div class="form-check">
                  <input
                    type="checkbox"
                    class="form-check-input"
                    name="data[mail_order]"
                    id="shipping"
                  />
                  <label class="form-check-label" for="shipping"
                    ><b>SHIPPING</b></label
                  >
                </div>
                <div class="form-check">
                  <input
                    type="checkbox"
                    class="form-check-input"
                    name="data[collect]"
                    id="collection"
                  />
                  <label class="form-check-label" for="collection"
                    ><b>COLLECTION</b></label
                  >
                </div>
              </div>

              <label>Send Shipping Email to:</label>
              <div id="emailsList">
                <div class="form-check" style="margin-bottom: 0.5rem">
                  <!-- THIS IS THE MULTIPLE I AM TRYING TO TOGGLE -->

                  <input
                    class="form-check-input billing"
                    type="checkbox"
                    data-parsley-multiple="selectOneEmail"
                    data-parsley-mincheck="1"
                    data-parsley-required
                    data-parsley-error-message="Please choose at least one email address"
                    id="send-contact-{{ list.contacts.order.billing.kContact }}"
                    name="to_emails[{{ list.contacts.order.billing.kContact }}]"
                  />
                  <label
                    class="form-check-label"
                    for="send-contact-{{ list.contacts.order.billing.kContact }}"
                  >
                    <b>Billing: </b>{{ list.contacts.order.billing.firstname }}
                    {{ list.contacts.order.billing.lastname }} &lt;{{
                    list.contacts.order.billing.email }}&gt;
                  </label>
                  <br />
                  <input
                    class="form-check-input delivery"
                    type="checkbox"
                    data-parsley-multiple="selectOneEmail"
                    id="send-contact-{{ list.contacts.order.delivery.kContact }}"
                    name="to_emails[{{ list.contacts.order.delivery.kContact }}]"
                  />
                  <label
                    class="form-check-label"
                    for="tracksend-contact-{{ list.contacts.order.delivery.kContact }}ingId"
                  >
                    <b>Delivery: </b>{{ list.contacts.order.delivery.firstname
                    }} {{ list.contacts.order.delivery.lastname }} &lt;{{
                    list.contacts.order.delivery.email }}&gt;
                  </label>
                </div>
              </div>

              <button type="select">COMPLETE</button>
            </form>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-primary">Save changes</button>
            <button
              type="button"
              class="btn btn-secondary"
              data-dismiss="modal"
            >
              Close
            </button>
          </div>
        </div>
      </div>
    </div>

  </body>
</html>