Form
.c-form
TODOs
- Replace native Constraint Validation API UI with custom JS validation
- Unify error rendering across native / Parsley / Powermail forms
Form.jscurrently 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.
- Nested instances: Input Fields, Selects, Buttons, Checkboxes, Radio Buttons etc.
- See Input Group for combinations of form elements.
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-validateto the input, textarea, or select field to be validated on every input or change event, seeFormValidation.js data-validation-error-message: Defines a custom validation error message.minlengthandmaxlength: Specifies the minimum and maximum length of textual data (strings).minandmax: 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.requiredattribute 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
<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
<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
<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
<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
<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
Show Code
<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
<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);