Font Face
Teva Sans Latin

Drafts & Templates
PBS Templates

Primitives & components context

Primitives & components: Teva Global

Form

v0.0.0

Contextual parts of a form, where fields should be displayed/hidden depending other field values can be placed in dropdown.

To collapse or expand content the Bootstrap Collapse is used. Inside the the element .collapse, the form elements are advised to be placed inside an element with class .vi-form__inset. It provides a visual queue (the border) to the optional form elements.

As per Bootstrap documentation, the trigger can be a button, or can be made dependent on a value of a field as displayed in following examples.

Note: The examples show possible technical implementations, since actual combinations of fields / triggers and validations are infinite.


Button as Trigger #

Example shows a Button used to expand / collapse the extra field.

<!-- Form  -->
<form action="#form-569452" autocomplete="off" class="vi-form vi-typesystem" data-validate="true" novalidate>
  <div class="form-group">
    <label for="control-b8ee54">Field 1
      <span aria-hidden="true" class="vi-form__required">(required)</span></label>
    <input aria-required="true" class="form-control" id="control-b8ee54" name="name-853775" placeholder="Field 1" required type="text">
  </div>
  <div class="form-group">
    <label for="control-b6479e">Field 2
      <span aria-hidden="true" class="vi-form__required">(required)</span></label>
    <input aria-required="true" class="form-control" id="control-b6479e" name="name-d43983" placeholder="Field 2" required type="text">
  </div>
  <div class="mb-20">
    <!-- Button type: outline  -->
    <button data-toggle="collapse" aria-expanded="false" data-target="#sg-170206" type="button" class="vi-btn-outline vi-btn-outline--no-pointer vi-btn">More Fields</button>
  </div>
  <div class="collapse" id="sg-170206">
    <div class="pb-20">
      <div class="vi-form__inset">
        <div class="form-group">
          <label for="control-186b65">Field 3
            <span aria-hidden="true" class="vi-form__required">(required)</span></label>
          <input aria-required="true" class="form-control" id="control-186b65" name="name-8b16d1" placeholder="Field 3" required type="text">
        </div>
      </div>
    </div>
  </div>
  <div>
    <!-- Button type: solid  -->
    <button type="submit" class="vi-btn-solid vi-btn">Submit</button>
  </div>
  <script>
    // see Bootstrap Documentation
    $(function() {
      var $collapsible = $('#sg-170206');

      $collapsible.find(':input').prop('disabled', true);
      $collapsible
      .on('shown.bs.collapse', function() {
        $collapsible.find(':input').prop('disabled', false);
      })
      .on('hidden.bs.collapse', function() {
        $collapsible.find(':input').prop('disabled', true);
      });
    });
  </script>
</form>

Expanded startingpoint example.

<!-- Form  -->
<form action="#form-92e20b" autocomplete="off" class="vi-form vi-typesystem" data-validate="true" novalidate>
  <div class="form-group">
    <label for="control-71bb1a">Field 1
      <span aria-hidden="true" class="vi-form__required">(required)</span></label>
    <input aria-required="true" class="form-control" id="control-71bb1a" name="name-d1b322" placeholder="Field 1" required type="text">
  </div>
  <div class="form-group">
    <label for="control-76c047">Field 2
      <span aria-hidden="true" class="vi-form__required">(required)</span></label>
    <input aria-required="true" class="form-control" id="control-76c047" name="name-8b6eee" placeholder="Field 2" required type="text">
  </div>
  <div class="mb-20">
    <!-- Button type: outline  -->
    <button data-toggle="collapse" aria-expanded="false" data-target="#sg-b0c9b6" type="button" class="vi-btn-outline vi-btn-outline--no-pointer vi-btn">Less Fields</button>
  </div>
  <div class="collapse show" id="sg-b0c9b6">
    <div class="pb-20">
      <div class="vi-form__inset">
        <div class="form-group">
          <label for="control-d77186">Field 3
            <span aria-hidden="true" class="vi-form__required">(required)</span></label>
          <input aria-required="true" class="form-control" id="control-d77186" name="name-854d55" placeholder="Field 3" required type="text">
        </div>
      </div>
    </div>
  </div>
  <div>
    <!-- Button type: solid  -->
    <button type="submit" class="vi-btn-solid vi-btn">Submit</button>
  </div>
  <script>
    // see Bootstrap Documentation
    $(function() {
      var $collapsible = $('#sg-b0c9b6');

      $collapsible.find(':input').prop('disabled', false);
      $collapsible
      .on('shown.bs.collapse', function() {
        $collapsible.find(':input').prop('disabled', false);
      })
      .on('hidden.bs.collapse', function() {
        $collapsible.find(':input').prop('disabled', true);
      });
    });
  </script>
</form>

Example shows a Button to add an array of extra fields

Do you want to add an extra item?

<!-- Form  -->
<form action="#form-be0d76" autocomplete="off" class="vi-form vi-typesystem" data-validate="true" novalidate>
  <div class="form-group">
    <label for="control-6eab8e">Field 1
      <span aria-hidden="true" class="vi-form__required">(required)</span></label>
    <input aria-required="true" class="form-control" id="control-6eab8e" name="name-c501dd" placeholder="Field 1" required type="text">
  </div>
  <div class="form-group">
    <label for="control-3704a7">Field 2
      <span aria-hidden="true" class="vi-form__required">(required)</span></label>
    <input aria-required="true" class="form-control" id="control-3704a7" name="name-52405b" placeholder="Field 2" required type="text">
  </div>
  <p class="mb-20">Do you want to add an extra item?</p>
  <div id="dynamic-fields-container"></div>
  <div class="mb-20">
    <!-- Button type: outline  -->
    <button id="add-item" type="button" class="vi-btn-outline vi-btn-outline--no-pointer vi-btn"><!-- Icon plus-sign (mods: --button-start) -->
      <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewbox="0 0 12 12" sg-icons-dir="sg/components/icon/icons" role="img" class="vi-icon vi-icon--button-start" aria-label="plus-sign"><polygon points="10 6 6 6 6 2 5 2 5 6 1 6 1 7 5 7 5 11 6 11 6 7 10 7"></polygon></svg>
      Add Item</button>
  </div>
  <div>
    <!-- Button type: solid  -->
    <button type="submit" class="vi-btn-solid vi-btn">Submit</button>
  </div>
  <script id="form-template" type="text/template">
    <div class="collapse" id="item-{{id0}}">
    <div class="pb-20">
    <div class="vi-form__inset">
    <div class="vi-flexbox flex-row-reverse justify-content-between">
    <!-- Button type: outline  -->
    <button id="button-{{id0}}" type="button" class="align-self-start vi-btn-outline vi-btn-outline--no-pointer vi-btn"><!-- Icon cross-sign (mods: --button-start) -->
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12" sg-icons-dir="sg/components/icon/icons" role="img" class="vi-icon vi-icon--button-start" aria-label="cross-sign" width="12" height="12"><path d="M10.5 2.5l-.7-.7-4.2 4.1-4.1-4.1-.7.7 4.1 4.1-4.1 4.2.7.7 4.1-4.2 4.2 4.2.7-.7-4.2-4.2z"></path></svg>


    Remove</button>
    <p class="text-dominant vi-type vi-type--header-regular">Add item</p>

    </div>
    <div class="form-group"><label for="sg-cea0c1-{{id0}}">Name
    <span aria-hidden="true" class="vi-form__required">(required)</span></label>
    <input aria-required="true" class="form-control" id="sg-cea0c1-{{id0}}" name="sg-cea0c1-{{id0}}" placeholder="Name" required type="text">



    </div><div class="form-group"><label for="sg-ba5b86-{{id0}}">Description
    <span aria-hidden="true" class="vi-form__required">(required)</span></label>
    <input aria-required="true" class="form-control" id="sg-ba5b86-{{id0}}" name="sg-ba5b86-{{id0}}" placeholder="Description" required type="text">



    </div><div class="form-group"><label for="sg-00755c-{{id0}}">Document
    <span aria-hidden="true" class="vi-form__required">(required)</span></label>
    <div class="custom-file">
    <input aria-required="true" class="custom-file-input" id="sg-00755c-{{id0}}" name="sg-00755c-{{id0}}" required type="file">
    <label class="custom-file-label" for="sg-00755c-{{id0}}">
    Please select a file

    </label>
    </div>


    </div><div class="form-group"><label for="sg-738291-{{id0}}">Item
    <span aria-hidden="true" class="vi-form__required">(required)</span></label>
    <select aria-required="true" class="custom-select" id="sg-738291-{{id0}}" name="sg-738291-{{id0}}" required>
    <option disabled="disabled" hidden="hidden" selected value="">Pick one
    </option>
    <option value="item-1">Item 1</option>
    <option value="item-2">Item 2</option>
    </select>


    </div><div class="form-group" id="group_id"><div class="custom-checkbox custom-control custom-control--top">
    <input aria-required="true" class="custom-control-input" id="sg-ee787e-{{id0}}" name="sg-ee787e-{{id0}}" required type="checkbox">
    <label class="custom-control-label" for="sg-ee787e-{{id0}}">
    Don't you agree?

    </label>
    </div>


    </div><div class="form-group"><div class="custom-checkbox custom-control">
    <input aria-required="true" class="custom-control-input" id="sg-d48773-{{id0}}" name="sg-d48773-{{id0}}" required type="checkbox">
    <label class="custom-control-label" for="sg-d48773-{{id0}}">
    Vegan pop-up flannel.

    </label>
    </div>

    <div class="custom-checkbox custom-control">
    <input aria-required="true" class="custom-control-input" id="sg-d48773-{{id0}}" name="sg-d48773-{{id0}}" required type="checkbox">
    <label class="custom-control-label" for="sg-d48773-{{id0}}">
    Pop-up 90's chia.

    </label>
    </div>

    <div class="custom-checkbox custom-control">
    <input aria-required="true" class="custom-control-input" id="sg-d48773-{{id0}}" name="sg-d48773-{{id0}}" required type="checkbox">
    <label class="custom-control-label" for="sg-d48773-{{id0}}">
    Bespoke irony fixie.

    </label>
    </div>

    <div class="custom-checkbox custom-control">
    <input aria-required="true" class="custom-control-input" id="sg-d48773-{{id0}}" name="sg-d48773-{{id0}}" required type="checkbox">
    <label class="custom-control-label" for="sg-d48773-{{id0}}">
    Twee authentic pour-over.

    </label>
    </div>


    </div><div class="form-group"><div class="custom-switch custom-control">
    <input aria-required="true" class="custom-control-input" id="sg-7ca610-{{id0}}" name="sg-7ca610-{{id0}}" required type="checkbox">
    <label class="custom-control-label" for="sg-7ca610-{{id0}}">
    Literally waistcoat selfies.

    </label>
    </div>


    </div><div class="form-group"><div class="custom-radio custom-control">
    <input aria-required="true" class="custom-control-input" id="sg-c2e719-{{id0}}" name="sg-c2e719-{{id0}}" required type="radio">
    <label class="custom-control-label" for="sg-c2e719-{{id0}}">
    Chillwave church-key taxidermy.

    </label>
    </div>

    <div class="custom-radio custom-control">
    <input aria-required="true" class="custom-control-input" id="sg-c2e719-{{id0}}" name="sg-c2e719-{{id0}}" required type="radio">
    <label class="custom-control-label" for="sg-c2e719-{{id0}}">
    Pitchfork migas pabst.

    </label>
    </div>

    <div class="custom-radio custom-control">
    <input aria-required="true" class="custom-control-input" id="sg-c2e719-{{id0}}" name="sg-c2e719-{{id0}}" required type="radio">
    <label class="custom-control-label" for="sg-c2e719-{{id0}}">
    Typewriter authentic slow-carb.

    </label>
    </div>


    </div><div class="vi-date-select" data-date-format="dd/mm/yy">
    <label class="mb-0 vi-date-select__label" for="sg-7bb20b-{{id0}}">
    Set a date
    </label>
    <div class="vi-date-select__trigger-container">
    <input autocomplete="off" class="datepicker-trigger custom-select form-control" id="sg-7bb20b-{{id0}}" name="sg-7bb20b-{{id0}}" placeholder="Choose date" required>
    <div class="vi-date-select__clear-container">
    <!-- Icon cross-sign  -->
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" sg-icons-dir="sg/components/icon/icons" role="img" class="vi-icon" aria-label="cross-sign" width="16" height="16"><path d="M14 3l-.8-.8-5.6 5.7L2 2.2l-.8.8 5.7 5.6-5.7 5.7.8.7 5.6-5.7 5.6 5.7.8-.7-5.7-5.7z"></path></svg>


    </div>
    </div>
    </div>
    <p class="mt-10 mb-0 text-muted small">The date-select component must be initialized after it's added to the DOM.</p>


    </div>
    </div>
    </div>
  </script>
  <script>
    $(function() {
      let formCounter = 0;

      $('#add-item').click(function() {
        formCounter++;

        // Create unique IDs using the counter
        const id0 = Math.random().toString(36).substr(2, 9);

        // Get the template and replace placeholders with the actual values
        let template = $('#form-template').html();
        template = template.replace(/{{id0}}/g, id0);

        // Append the filled template to the dynamic fields container
        $('#dynamic-fields-container').viFormDynamicFieldsContainer().append(template);

        // Line to initialize date select (only new ones will be initialized)
        $('#dynamic-fields-container').find('.vi-date-select').viDateSelect()

        $(`#item-${id0}`).collapse('show')

        // Add close behavour
        $(`#button-${id0}`).on('click', function() {
          // see Bootstrap Documentation
          $(`#item-${id0}`).collapse('hide').on('hidden.bs.collapse', function() {
            $(this).collapse('dispose').remove();
          });
        })
      });
    });
  </script>
</form>

Checkbox as Trigger #

Example shows a checkbox used to expand / collapse the extra field.

Please see source code for the javascript to create the behaviour.

<!-- Form  -->
<form action="#form-5c927b" autocomplete="off" class="vi-form vi-typesystem" data-validate="true" novalidate>
  <div class="form-group">
    <label for="control-e57595">Field 1
      <span aria-hidden="true" class="vi-form__required">(required)</span></label>
    <input aria-required="true" class="form-control" id="control-e57595" name="name-daec1d" placeholder="Field 1" required type="text">
  </div>
  <div class="form-group" id="sg-39bbc5">
    <div class="custom-checkbox custom-control custom-control--top">
      <input class="custom-control-input" id="control-5d8014" name="name-e1b226" type="checkbox">
      <label class="custom-control-label" for="control-5d8014">
        More options
      </label>
    </div>
  </div>
  <div class="collapse" id="sg-2add21">
    <div class="pb-20">
      <div class="vi-form__inset">
        <div class="form-group">
          <label for="control-ec9582">Field 2
            <span aria-hidden="true" class="vi-form__required">(required)</span></label>
          <input aria-required="true" class="form-control" id="control-ec9582" name="name-c54ba6" placeholder="Field 2" required type="text">
        </div>
      </div>
    </div>
  </div>
  <div>
    <!-- Button type: solid  -->
    <button type="submit" class="vi-btn-solid vi-btn">Submit</button>
  </div>
  <script>
    // see Bootstrap Documentation
    $(function() {
      var $collapsible = $('#sg-2add21');
      $collapsible.find(':input').prop('disabled', true);

      $('#sg-39bbc5 input').on('change', function() {
        if ( $(this).is(':checked') ) {
          $collapsible.collapse('show').find(':input').prop('disabled', false);
        } else {
          $collapsible.collapse('hide').find(':input').prop('disabled', true);
        }
      });
    });
  </script>
</form>

Expanded startingpoint example.

<!-- Form  -->
<form action="#form-87db4b" autocomplete="off" class="vi-form vi-typesystem" data-validate="true" novalidate>
  <div class="form-group">
    <label for="control-5dd718">Field 1
      <span aria-hidden="true" class="vi-form__required">(required)</span></label>
    <input aria-required="true" class="form-control" id="control-5dd718" name="name-593104" placeholder="Field 1" required type="text">
  </div>
  <div class="form-group" id="sg-2a4c3e">
    <div class="custom-checkbox custom-control custom-control--top">
      <input checked class="custom-control-input" id="control-551929" name="name-6a1e8a" type="checkbox">
      <label class="custom-control-label" for="control-551929">
        Less options
      </label>
    </div>
  </div>
  <div class="collapse show" id="sg-c605c9">
    <div class="pb-20">
      <div class="vi-form__inset">
        <div class="form-group">
          <label for="control-de9a27">Field 2
            <span aria-hidden="true" class="vi-form__required">(required)</span></label>
          <input aria-required="true" class="form-control" id="control-de9a27" name="name-ddd4b3" placeholder="Field 2" required type="text">
        </div>
      </div>
    </div>
  </div>
  <div>
    <!-- Button type: solid  -->
    <button type="submit" class="vi-btn-solid vi-btn">Submit</button>
  </div>
  <script>
    // see Bootstrap Documentation
    $(function() {
      var $collapsible = $('#sg-c605c9');
      $collapsible.find(':input').prop('disabled', false);

      $('#sg-2a4c3e input').on('change', function() {
        if ( $(this).is(':checked') ) {
          $collapsible.collapse('show').find(':input').prop('disabled', false);
        } else {
          $collapsible.collapse('hide').find(':input').prop('disabled', true);
        }
      });
    });
  </script>
</form>

Radio Buttons as Trigger #

Example shows radio buttons used to expand / collapse the extra fields.

Please see source code for the javascript to create the behaviour.

<!-- Form  -->
<form action="#form-698c73" autocomplete="off" class="vi-form vi-typesystem" data-validate="true" novalidate>
  <div class="form-group">
    <label for="control-7142bb">Field 1
      <span aria-hidden="true" class="vi-form__required">(required)</span></label>
    <input aria-required="true" class="form-control" id="control-7142bb" name="name-80b17b" placeholder="Field 1" required type="text">
  </div>
  <div class="form-group" id="sg-d79a95">
    <div class="custom-radio custom-control">
      <input aria-required="true" class="custom-control-input" id="control-9e1844" name="name-8d0584" required type="radio" value="sg-5677de">
      <label class="custom-control-label" for="control-9e1844">
        Show Field 2
      </label>
    </div>
    <div class="collapse" id="sg-5677de">
      <div class="py-10">
        <div class="vi-form__inset">
          <div class="form-group">
            <label for="control-024c8d">Field 2
              <span aria-hidden="true" class="vi-form__required">(required)</span></label>
            <input aria-required="true" class="form-control" id="control-024c8d" name="name-ca694a" placeholder="Field 2" required type="text">
          </div>
        </div>
      </div>
    </div>
    <div class="custom-radio custom-control">
      <input aria-required="true" class="custom-control-input" id="control-1ae54a" name="name-8d0584" required type="radio" value="sg-c634c6">
      <label class="custom-control-label" for="control-1ae54a">
        Show Field 3
      </label>
    </div>
    <div class="collapse" id="sg-c634c6">
      <div class="py-10">
        <div class="vi-form__inset">
          <div class="form-group">
            <label for="control-7997d9">Field 3
              <span aria-hidden="true" class="vi-form__required">(required)</span></label>
            <input aria-required="true" class="form-control" id="control-7997d9" name="name-68bb55" placeholder="Field 3" required type="text">
          </div>
        </div>
      </div>
    </div>
  </div>
  <div>
    <!-- Button type: solid  -->
    <button type="submit" class="vi-btn-solid vi-btn">Submit</button>
  </div>
  <script>
    // see Bootstrap Documentation
    $(function() {
      $('#sg-d79a95 input').on('change', function() {

        var $input = $(this);
        var $visibleCollapable = $input.parents('.vi-form').find('.collapse.show');
        var $hiddenCollapse    = $('#' + $input.val());


        if ($visibleCollapable.length) {
          // wait until the visible collapse is hidden.
          $visibleCollapable.one('hidden.bs.collapse', function() {
            $hiddenCollapse.collapse('show').find(':input').prop('disabled', false);
          }).collapse('hide').find(':input').prop('disabled', true);
        } else {
          $hiddenCollapse.collapse('show').find(':input').prop('disabled', false);
        }
      }).parents('.vi-form').find('.collapse').find(':input').prop('disabled', true);
    });
  </script>
</form>

Expanded startingpoint example.

<!-- Form  -->
<form action="#form-d88335" autocomplete="off" class="vi-form vi-typesystem" data-validate="true" novalidate>
  <div class="form-group">
    <label for="control-507e63">Field 1
      <span aria-hidden="true" class="vi-form__required">(required)</span></label>
    <input aria-required="true" class="form-control" id="control-507e63" name="name-3cc6c0" placeholder="Field 1" required type="text">
  </div>
  <div class="form-group" id="sg-59ab6e">
    <div class="custom-radio custom-control">
      <input aria-required="true" checked class="custom-control-input" id="control-95693d" name="name-8d0584" required type="radio" value="sg-557b64">
      <label class="custom-control-label" for="control-95693d">
        Show Field 2
      </label>
    </div>
    <div class="collapse show" id="sg-557b64">
      <div class="py-10">
        <div class="vi-form__inset">
          <div class="form-group">
            <label for="control-4b95c8">Field 2
              <span aria-hidden="true" class="vi-form__required">(required)</span></label>
            <input aria-required="true" class="form-control" id="control-4b95c8" name="name-1ad94a" placeholder="Field 2" required type="text">
          </div>
        </div>
      </div>
    </div>
    <div class="custom-radio custom-control">
      <input aria-required="true" class="custom-control-input" id="control-5c2954" name="name-8d0584" required type="radio" value="sg-2e3815">
      <label class="custom-control-label" for="control-5c2954">
        Show Field 3
      </label>
    </div>
    <div class="collapse" id="sg-2e3815">
      <div class="py-10">
        <div class="vi-form__inset">
          <div class="form-group">
            <label for="control-163a08">Field 3
              <span aria-hidden="true" class="vi-form__required">(required)</span></label>
            <input aria-required="true" class="form-control" id="control-163a08" name="name-c0d4d5" placeholder="Field 3" required type="text">
          </div>
        </div>
      </div>
    </div>
  </div>
  <div>
    <!-- Button type: solid  -->
    <button type="submit" class="vi-btn-solid vi-btn">Submit</button>
  </div>
  <script>
    // see Bootstrap Documentation
    $(function() {
      $('#sg-59ab6e input').on('change', function() {

        var $input = $(this);
        var $visibleCollapable = $input.parents('.vi-form').find('.collapse.show');
        var $hiddenCollapse    = $('#' + $input.val());


        if ($visibleCollapable.length) {
          // wait until the visible collapse is hidden.
          $visibleCollapable.one('hidden.bs.collapse', function() {
            $hiddenCollapse.collapse('show').find(':input').prop('disabled', false);
          }).collapse('hide').find(':input').prop('disabled', true);
        } else {
          $hiddenCollapse.collapse('show').find(':input').prop('disabled', false);
        }
      }).parents('.vi-form').find('.collapse:not(.show)').find(':input').prop('disabled', true);
    });
  </script>
</form>

Select field as Trigger #

Example shows select fiels used to expand / collapse the extra fields.

Please see source code for the javascript to create the behaviour.

<!-- Form  -->
<form action="#form-b7d906" autocomplete="off" class="vi-form vi-typesystem" data-validate="true" novalidate>
  <div class="form-group">
    <label for="control-dc6ae3">Field 1
      <span aria-hidden="true" class="vi-form__required">(required)</span></label>
    <input aria-required="true" class="form-control" id="control-dc6ae3" name="name-1874b3" placeholder="Field 1" required type="text">
  </div>
  <div class="form-group" id="sg-9ea962">
    <label for="control-50b5ae">Choose option.
      <span aria-hidden="true" class="vi-form__required">(required)</span></label>
    <select aria-required="true" class="custom-select" id="control-50b5ae" name="name-6732a2" required>
      <option disabled hidden="hidden" selected value="">Choose
      </option>
      <option value="other-option-x">Other option x</option>
      <option value="show-field-2">Show Field 2</option>
      <option value="other-option-y">Other option y</option>
      <option value="other-option-z">Other option z</option>
    </select>
  </div>
  <div class="collapse" id="sg-bd7758">
    <div class="pb-20">
      <div class="vi-form__inset">
        <div class="form-group">
          <label for="control-bbbdde">Field 2
            <span aria-hidden="true" class="vi-form__required">(required)</span></label>
          <input aria-required="true" class="form-control" id="control-bbbdde" name="name-84e8b8" placeholder="Field 2" required type="text">
        </div>
      </div>
    </div>
  </div>
  <div>
    <!-- Button type: solid  -->
    <button type="submit" class="vi-btn-solid vi-btn">Submit</button>
  </div>
  <script>
    // see Bootstrap Documentation
    $(function() {
      var $collapsible = $('#sg-bd7758');
      $collapsible.find(':input').prop('disabled', true);

      $('#sg-9ea962 select').on('change', function() {
        var $input = $(this);

        if ($input.val() == 'show-field-2') {
          $collapsible.collapse('show').find(':input').prop('disabled', false);
        } else {
          $collapsible.collapse('hide').find(':input').prop('disabled', true);
        }

      });
    });
  </script>
</form>

Expanded startingpoint example.

<!-- Form  -->
<form action="#form-898a26" autocomplete="off" class="vi-form vi-typesystem" data-validate="true" novalidate>
  <div class="form-group">
    <label for="control-240300">Field 1
      <span aria-hidden="true" class="vi-form__required">(required)</span></label>
    <input aria-required="true" class="form-control" id="control-240300" name="name-47401c" placeholder="Field 1" required type="text">
  </div>
  <div class="form-group" id="sg-267e61">
    <label for="control-35a104">Choose option.
      <span aria-hidden="true" class="vi-form__required">(required)</span></label>
    <select aria-required="true" class="custom-select" id="control-35a104" name="name-73b962" required>
      <option disabled hidden="hidden" selected value="">Choose
      </option>
      <option value="other-option-x">Other option x</option>
      <option selected value="show-field-2">Show Field 2</option>
      <option value="other-option-y">Other option y</option>
      <option value="other-option-z">Other option z</option>
    </select>
  </div>
  <div class="collapse show" id="sg-980110">
    <div class="pb-20">
      <div class="vi-form__inset">
        <div class="form-group">
          <label for="control-1b162c">Field 2
            <span aria-hidden="true" class="vi-form__required">(required)</span></label>
          <input aria-required="true" class="form-control" id="control-1b162c" name="name-4248bc" placeholder="Field 2" required type="text">
        </div>
      </div>
    </div>
  </div>
  <div>
    <!-- Button type: solid  -->
    <button type="submit" class="vi-btn-solid vi-btn">Submit</button>
  </div>
  <script>
    // see Bootstrap Documentation
    $(function() {
      var $collapsible = $('#sg-980110');
      $collapsible.find(':input').prop('disabled', false);

      $('#sg-267e61 select').on('change', function() {
        var $input = $(this);

        if ($input.val() == 'show-field-2') {
          $collapsible.collapse('show').find(':input').prop('disabled', false);
        } else {
          $collapsible.collapse('hide').find(':input').prop('disabled', true);
        }

      });
    });
  </script>
</form>

Miscellaneous #

Example shows a form with two kinds of checkbox fields.

Normal checkboxes and checkboxes that control contextual fields.

<!-- Form  -->
<form action="#form-b74807" autocomplete="off" class="vi-form vi-typesystem" data-validate="true" novalidate>
  <div class="form-group" id="context-b03721">
    <div class="custom-checkbox custom-control">
      <input class="custom-control-input" id="control-cb6e9d" name="name-5807bb" type="checkbox">
      <label class="custom-control-label" for="control-cb6e9d">
        Normal checkbox
      </label>
    </div>
    <div class="custom-checkbox custom-control">
      <input class="custom-control-input" data-collapse-id="context-575624" id="control-c841a8" name="name-082440" type="checkbox">
      <label class="custom-control-label" for="control-c841a8">
        More options
      </label>
    </div>
    <div class="collapse" id="context-575624">
      <div class="py-10">
        <div class="vi-form__inset">
          <div class="form-group">
            <label for="control-a174b5">Extra Field 1
              <span aria-hidden="true" class="vi-form__required">(required)</span></label>
            <input aria-required="true" class="form-control" id="control-a174b5" name="name-7b5c12" placeholder="Extra Field 1" required type="text">
          </div>
        </div>
      </div>
    </div>
    <div class="custom-checkbox custom-control">
      <input class="custom-control-input" id="control-146158" name="name-a21852" type="checkbox">
      <label class="custom-control-label" for="control-146158">
        Normal checkbox
      </label>
    </div>
    <div class="custom-checkbox custom-control" id="context-034b8c">
      <input class="custom-control-input" data-collapse-id="context-640479" id="control-7d838b" name="name-c9b90b" type="checkbox">
      <label class="custom-control-label" for="control-7d838b">
        More options
      </label>
    </div>
    <div class="collapse" id="context-640479">
      <div class="py-10">
        <div class="vi-form__inset">
          <div class="form-group">
            <label for="control-1a732e">Extra Field 2
              <span aria-hidden="true" class="vi-form__required">(required)</span></label>
            <input aria-required="true" class="form-control" id="control-1a732e" name="name-7597ac" placeholder="Extra Field 2" required type="text">
          </div>
        </div>
      </div>
    </div>
  </div>
  <div>
    <!-- Button type: solid  -->
    <button type="submit" class="vi-btn-solid vi-btn">Submit</button>
  </div>
  <script>
    // see Bootstrap Documentation on collapse

    // The contextual part.
    $(function() {
      $('#context-b03721 input[data-collapse-id]').on('change', function() {

        var $input   = $(this);
        var checked  = $input.is(':checked')
        var $content = $('#' + $input.data('collapse-id'));

        if (!$content.length) return;

        if (checked) {
          $content.collapse('show').find(':input').prop('disabled', false);
        } else {
          $content.collapse('hide').find(':input').prop('disabled', true);
        }
      })
      $('#context-b03721').find('.collapse:not(.show)').find(':input').prop('disabled', true);
    });

    // The validation part.
    $('#context-034b8c').on('validate', function(e, field, isValid, eventType) {

      if (eventType != 'submit') return;

      // if all checkboxed in group checked.
      if ($('#context-b03721 :checkbox:checked').length) {
        isValid(true)
      } else {
        isValid(false, 'Please select at least one box');
      }
    });
  </script>
</form>

Stylesheets #

The following stylesheets are required to display this component.

The following additional stylesheet is used to display the example(s).


JavaScript #

The following javascripts are required to display this component.


Usage documentation #

Usage documentation can be found here.


Changelog #

Changelog

Fix

  • 19 Feb 2025 - fix(form): resolve mutation observer recursion issue in Safari
  • 13 Feb 2025 - feat(form): fix form reset validation messages
  • 11 Sep 2024 - Fix broken label issue (webkit only!)
  • 01 Jun 2023 - Fix read-only styling to input, select and textarea. Fixes placeholder combobox.
  • 23 May 2023 - Removed a11y default success message; Business requirement.
  • 28 Apr 2023 - Fix safaris hard disable color override.
  • 15 Feb 2023 - Combobox validation
  • 18 Jan 2023 - Fix background-clip setting.
  • 28 June 2022 - Fix scrollparent detector
  • Make Safari (the new IE6) understand how parenthesis work when direction is rtl.
  • Remove previous work around.
  • Try to work around chrome mobile bug (1197882) where long datalists overlap keyboard.
  • Fix chrome bug (674447, 849616) where datalist gets detached by scrolling.
  • Wrapping of lang filenames in file field.
  • PBS support: fix box-shadow on custom-control
  • Regression: accent colors not picked up by sass.
  • Allow re-enabled fields to validate.
  • Remove file field blur validation.
  • A11y: …show hidden span tag with this value”name of the file + “selected” add role=”alert”
  • A11y: Redundantly add attribute aria-required=true to elements with attribute required
  • A11y: …add a hidden span tag with this value”name of the file + “uploaded” add role=”alert”
  • Form Validation message not showing, when element hidden.
  • IE11 premature error throwing.
  • Better align custom indicators regardless font / line-height used.
  • Remove background color IE11 from focused select.

Changed

  • 09 Jan 2025 - feat(multiple-select): Show options with empty value.
  • 30 Jun 2023 - Disabled state of checkbox/radio and switch.

Added

  • 28 Aug 2024 - Add dynamic form fields example + added $.fn.viFormDynamicFieldsContainer() to assign to a dynamic fields container and keep validation in sync.
  • 17 May 2023 - Form reset removes validation messages.
  • 15 Mar 2023 - Allow browse button text to be changed.
  • 15 Feb 2023 - Combobox reset
  • 2 Dec 2022 - Add size sm size to text-fields.
  • 14 Nov 2022 - Add data attribute data-keyup to allow for keyup validation on a field. (required by wizard#contextual-fields)
  • Add an example of a paragraph
  • An example of labels on select fields.
  • PBS support
  • Examples of contextual form fields.
  • Add --top modifier to .custom-control for long labels.
  • A11y: File field focus outline same as links.
  • On submit focus on first invalid element
  • Missing File Browser field
  • RTL support
  • Documentation
  • Changed checkbox outline according new design input.
  • Initial draft