Skip to content

Form ​

.c-form

TODOs

  • Replace native Constraint Validation API UI with custom JS validation
  • Unify error rendering across native / Parsley / Powermail forms
  • Form.js currently bundles three unrelated things: float-label state, validation, and the search/inline-button behavior -> break into seperate files, replace

The Form-Module handles the general form styles and styles for additional elements like CAPTCHA images or Powermail / Parsley error messages. It also handles the general functionality for input fields like the Float Container, the Clear-Search-Button and the Data-Activate-Btn.

Form Validation ​

Planned Change

We are moving away from relying on the browser's native Constraint Validation API UI (the built-in validation "bubbles"/tooltips) in favor of a fully custom, JS-driven validation layer using Float Container Hints.

Reasons: The native validation bubble cannot be styled or positioned to match our design (see the .-validate-warning and error-message patterns below, which already work around this), its appearance and behavior differ across browsers and mobile devices, and it doesn't compose cleanly with the Parsley- and Powermail-based validation already used elsewhere in this module (see Example Forms below). The goal is one consistent validation/error-rendering path instead of three coexisting ones.

The attributes documented below remain valid HTML and will keep working. What changes is how errors are displayed — via our own markup instead of the browser's native UI. Until this migration lands, existing implementations are unaffected.

The Form-Module uses the Constraint Validation API to validate form fields.

  • add the class js-validate to the input, textarea, or select field to be validated on every input or change event, see FormValidation.js
  • data-validation-error-message: Defines a custom validation error message.
  • minlength and maxlength: Specifies the minimum and maximum length of textual data (strings).
  • min and max: Specifies the minimum and maximum values of numerical input types.
  • type: Specifies whether the data needs to be a number, an email address, or some other specific preset type.
  • pattern: Specifies a regular expression that defines a pattern the entered data needs to follow.
  • required attribute is also needed, otherwise an input field with an empty value will be excluded from constraint validation.

Example Error Message ​

.js-validate[required][data-validation-error-message="Mindestens 3 Zeichen eingeben"][minlength="3"]

Click into the input field and then click somewhere else to see the error styling.

Show Code
html
<div class="c-float-container">
  <label class="c-label" for="example-input-validation01">Name (must be 3 characters long) *</label>
  <input type="text"
         class="c-input js-validate"
         required
         data-validation-error-message="Mindestens 3 Zeichen eingeben"
         minlength="3"
         name=""
         value=""
         id="example-input-validation01"
         data-placeholder="Type at least 3 characters ..." />
</div>

Example Warning Styling ​

Add .-validate-warning class to the container for warning input styling.

Show Code
html
<div class="c-float-container -validate-warning -has-input">
  <label class="c-label" for="input23-test">Name *</label>
  <input type="text" class="c-input js-validate" required data-validation-error-message="Mindestens 3 Zeichen eingeben" minlength="3" name="" value="" id="input23-test" data-placeholder="type at least 3 characters ..." />
</div>

Date Input Demo with Pattern ​

Type a date in the format dd.mm.yyyy.

Show Code
html
<input type="text" class="c-input -old js-validate" name="" value="" pattern="(0[1-9]|[12][0-9]|3[01])\.(0[1-9]|1[0-2])\.(\d\d\d\d)" />

Demo with Input-Group ​

Type something - only numbers are allowed.

Show Code
html
<div class="c-input-wrap">
  <select class="c-select -old js-select2" name="opts" data-additional-classes="-old">
    <option value='1'>mg</option>
    <option value='2'>g</option>
    <option value='3'>I.E.</option>
  </select>
  <div class="c-input-wrap__input">
    <input class="c-input -old js-validate"
           data-validation-error-message="Nur Zahlen erlaubt"
           pattern="^[0-9]+$"
           required />
  </div>
</div>

Input with Disabled Icon-Button ​

Add the data-min-amount attribute to activate the button when the user inserts a minimum amount of characters. The minimum amount is defined via the extra attribute data-min-amount="5".

Show Code
html
<div class="c-float-container -has-input -has-btn" data-activate-btn data-min-amount="5">
  <label class="c-label" for="input-button-disabled">Filter speichern</label>
  <input type="text" class="c-input" data-placeholder="Filter-Namen eingeben (mindestens 5 Buchstaben)" id="input-button-disabled" name="" value="" />
  <button type="button" disabled
          class="c-btn -square-btn -primary -input js-tooltip" data-title="Bitte Namen eingeben" data-placement="left">
    <i class="far fa-save" aria-hidden="true"></i>
    <span class="h-sr-only">Speichern</span>
  </button>
</div>

Example Forms ​

Example integrations used on the pharma4u website.

Parsley Form ​

  • Bitte wählen Sie einen Abo-Typ aus.
    • Dies ist ein Pflichtfeld.
    • Dies ist ein Pflichtfeld.
      • Bitte wählen Sie eine Option.
      Vorheriger SchrittNächster Schritt
      Show Code
      html
      <div id="erroraccounttyp">
        <ul class="parsley-errors-list filled">
          <li class="parsley-custom-error-message">Bitte wählen Sie einen Abo-Typ aus.</li>
        </ul>
      </div>
      
      <div class="h-highlight-block h-fullwidth-block m-y-m">
        <fieldset>
          <div class="h-width-60 h-center">
            <div class="c-float-container -has-select -light -is-active">
              <label class="c-label" for="title">Titel</label>
              <select class="c-select js-select2" id="title" data-parsley-id="2877"><option value="" selected="selected"> </option>
                <option value="Dr.">Dr.</option>
                <option value="Prof.">Prof.</option>
                <option value="Priv.-Doz.">Priv.-Doz.</option>
              </select><ul class="parsley-errors-list" id="parsley-id-2877"></ul>
            </div>
            <div class="c-float-container -has-input -light">
              <label class="c-label" for="firstName">Vorname*</label>
              <input data-parsley-errors-container="#errorfirstName" required="" data-parsley-minlength="2" data-parsley-minlength-message="Bitte tragen Sie mindestens 2 Zeichen ein" data-parsley-trigger="focusout" data-parsley-group="block1" class="c-input" id="firstName" type="text" name="tx_registration_base[newFrontendUser][firstName]" data-parsley-id="9186">
            </div>
            <div class="c-float-container -has-input -light parsley-error">
              <div id="errorlastName" class="errorHolder"><ul class="parsley-errors-list filled" id="parsley-id-3150"><li class="parsley-required">Dies ist ein Pflichtfeld.</li></ul></div>
              <label class="c-label" for="lastName">
                Nachname*
              </label>
              <input data-parsley-errors-container="#errorlastName" required="" data-parsley-minlength="2" data-parsley-minlength-message="Bitte tragen Sie mindestens 2 Zeichen ein" data-parsley-trigger="focusout" data-parsley-group="block1" class="c-input" id="lastName" type="text" name="tx_registration_base[newFrontendUser][lastName]" data-parsley-id="3150">
            </div>
            <div class="c-float-container -has-input -light parsley-error">
              <div id="erroraddress" class="errorHolder"><ul class="parsley-errors-list filled" id="parsley-id-7879"><li class="parsley-required">Dies ist ein Pflichtfeld.</li></ul></div>
              <label class="c-label" for="address">
                Straße, Nr.*
              </label>
              <input data-parsley-errors-container="#erroraddress" required="" data-parsley-trigger="focusout" data-parsley-group="block1" class="c-input" id="address" type="text" name="tx_registration_base[newFrontendUser][address]" data-parsley-id="7879">
            </div>
            <div class="c-float-container -has-input -light -is-active parsley-success">
              <div id="errorzip" class="errorHolder"><ul class="parsley-errors-list" id="parsley-id-5094"></ul></div>
              <label class="c-label" for="zip">
                PLZ*
              </label>
              <input data-parsley-errors-container="#errorzip" required="" data-parsley-trigger="focusout" data-parsley-group="block1" class="c-input" id="zip" type="text" name="tx_registration_base[newFrontendUser][zip]" data-parsley-id="5094" data-com.agilebits.onepassword.user-edited="yes">
            </div>
            <div class="c-float-container -has-select -light -is-active parsley-error">
              <div id="errorstatus" class="errorHolder"><ul class="parsley-errors-list filled" id="parsley-id-9297"><li class="parsley-min">Bitte wählen Sie eine Option.</li></ul></div>
              <label class="c-label" for="status">
                Status*
              </label>
              <select data-parsley-errors-container="#errorstatus" required="" data-parsley-min="1" data-parsley-group="block1" data-parsley-trigger="focusout" class="c-select js-select2" id="status" name="tx_registration_base[newFrontendUser][status]" data-parsley-id="9297"><option value="0"></option>
                <option value="4">Apotheker</option>
                <option value="8">Institution der Pharmazie</option>
                <option value="3">Pharmazeut im Praktikum (PiP)</option>
              </select>
            </div>
            <div class="c-float-container -has-input -light">
              <label class="c-label" for="capture">Captcha</label>
              <input type="text" class="c-input" name="tx_veguestbook_pi1[captcha_response]" value="" id="capture">
              <img src="https://placehold.co/130x50" alt="">
            </div>
            <div class="c-float-container -has-textarea -light">
              <label class="c-label" for="textarea1">Floating Label</label>
              <textarea class="c-textarea" name="" id="textarea1" cols="30" rows="3" data-placeholder=".. and Placeholder Text">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
              </textarea>
            </div>
          </div>
          <div class="c-form__bottom h-center h-width-90">
            <span class="c-btn -secondary -icon-left -icon-arrow" data-current-block="1" data-next-block="0">Vorheriger Schritt</span>
            <span class="c-btn -primary -icon-right -icon-arrow" data-current-block="1" data-next-block="2">Nächster Schritt</span>
          </div>
        </fieldset>
      </div>

      Powermail Form ​

      .c-float-container > .error-msg

      Show Code
      html
      <div class="subscribe-newsletter">
        <div class="c-float-container -has-input">
          <label class="c-label" for="fe_ttaddress_name_input">Name*</label>
          <span class="error-msg">Dies ist ein Pflichtfeld!</span>
          <input type="text" class="c-input" name="FE[tt_address][name]" id="fe_ttaddress_name_input">
        </div>
        <div class="c-float-container -has-input">
          <label class="c-label" for="fe_ttaddress_email_input">E-Mail*</label>
          <span class="error-msg">Dies ist ein Pflichtfeld! Dies ist keine gültige E-Mail-Adresse!</span>
          <input type="text" class="c-input" name="FE[tt_address][email]" id="fe_ttaddress_email_input">
        </div>
        <div class="c-form__bottom">
          <button class="c-btn -primary" type="submit" name="whatever">Newsletter abonnieren</button>
        </div>
      </div>

      Settings and API ​

      Initializes the Form Module with or without custom settings and registers Event-Listeners:
      Form.init(settings: object);

      Activate Float:
      Form.activateFloat(element: Node);

      Deactivate Float:
      Form.deactivateFloat(element: Node);

      Activate disabled button:
      Form.activateInlineBtn(button: Node);

      Initializes the Form Validation with or without custom settings and registers Event-Listeners:
      FormValidation.init(settings: object);