Optional Requirements

There may come a time when you have a form that has optional requirements. By that I mean that depending on a previous selection, future selections may become required, or not.

A simple method I've found to do this is with jQuery on the front end and no validation requirements on the back end. An example follows:

A Contact of either type "business" or "individual" needs to be entered. One or the other must be entered, but we don't want to require the business information for an individual, or vice versa. So we can enable/disable the requirements and display or hide the sections based on the selection.

First, in the default layout, /templates/Layout/default.php, we load jQuery by adding the following line in the head section:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>

Then for our form /template/Contact/add.php, we add a choice field and use jQuery to show and hide, and enable or disable "required" flags.

<?php echo $this->Form->control('contact', ['type' => 'radio', 'label' => 'Contact is:', 'options' => ['Business', 'Individual'], 'required' => true]); ?>
<div class="business" style="display:none">
  <?php
    echo $this->Form->control('business_name', ['required' => true]);
    echo $this->Form->control('business_telephone');
    echo $this->Form->control('business_address', ['required' => true]);
    echo $this->Form->control('business_city', ['required' => true]);
    echo $this->Form->control('business_state', ['required' => true, 'options' => $states]);
    echo $this->Form->control('business_zip', ['required' => true]);
  ?>
</div>
<div class="individual" style="display:none">
  <?php
    echo $this->Form->control('name', ['required' => true]);
    echo $this->Form->control('telephone', ['required' => true]);
  ?>
</div>
<script>
  if (jQuery('#contact-0').is(':checked')) {
    showAndRequire('.business', true);
    showAndRequire('.individual', false);
  } else if (jQuery('#contact-1').is(':checked')) {
    showAndRequire('.individual', true);
    showAndRequire('.business', false);
  }
  jQuery('#contact-0').click(function() {
    showAndRequire('.business', true);
    showAndRequire('.individual', false);
  });
  jQuery('#contact-1').click(function() {
    showAndRequire('.individual', true);
    showAndRequire('.business', false);
  });
  function showAndRequire(section, onOff) {
    jQuery(section).toggle(onOff);
    if (onOff) {
      jQuery(section + ' .required input').attr('required', onOff);
      jQuery(section + ' .required select').attr('required', onOff);
    } else {
      jQuery(section + ' .required input').removeAttr('required');
      jQuery(section + ' .required select').removeAttr('required');
    }
  }
</script>

Now when a user selects business or individual, only that section will be displayed and only that section will have the required attributes set.