Lion Logo Lion Guides Components Docs Blog Toggle darkmode

Form: Validate

When validation happens

Validation happens on every change of modelValue. A change in modelValue can be originated from either user interaction or an imperative action from an Application Developer. We could therefore say validation happens 'realtime'. This is aligned with the platform.

When validation feedback will be shown

Although validation happens realtime under the hood, displaying validity feedback in realtime may not always lead to the desired User Experience. Together with interaction states, validity states can determine whether a validation message should be shown along the input field.

Assessing field validation state programmatically

When a field has validation feedback it can be accessed using the hasFeedbackFor and showsFeedbackFor properties. This can be used if the validity of the field is needed in code.

  • hasFeedbackFor is the state of the field regardless of whether the feedback is shown or not.
  • showsFeedbackFor represents whether or not validation feedback is being shown. This takes into account interaction state such as a field being touched and dirty, prefilled or submitted
// Field is invalid and has not interacted with
const field = document.querySelector('#my-field');
field.hasFeedbackFor.includes('error'); // returns true
field.showsFeedbackFor.includes('error'); // returns false

// Field  invalid, dirty and touched
field.hasFeedbackFor.includes('error'); // returns true
field.showsFeedbackFor.includes('error'); // returns true

Features

  • Allow for advanced UX scenarios by updating validation state on every value change
  • Provide a powerful way of writing validation via pure functions
  • Default validators
  • Custom validators
  • Multiple validation types(error, warning, info, success)

Our validation system is designed to:

  • Allow for advanced UX scenarios by updating validation state on every value change
  • Provide a powerful way of writing validations via classes.

Validators

All validators are extensions of the Validator class. They should be applied to the element implementing ValidateMixin as follows:

<validatable-el
  .validators="${[new MyValidator({ myParam: 'foo' }), { extra: 'options' } ]]}"
></validatable-el>

As you can see the 'validators' property expects a map (an array of arrays). So, every Validator is a class consisting of:

  • validator function
  • validator parameters (optional)
  • validator config (optional)

Validator classes

All validators extend from the default Validator class. Below example is an example of a validator could look like:

class MyValidator extends Validator {
  execute(modelValue, param) {
    const hasFeedback = false;
    if (modelValue === param) {
      hasFeedback = true;
    }
    return hasFeedback;
  }

  static get validatorName() {
    return 'Required';
  }

  static getMessage({ fieldName }) {
    return `Please fill in ${fieldName}`;
  }
}
<validatable-el .validators="${[new MyValidator('foo')]}"></validatable-el>

Installation

npm i --save @lion/form-core
import '@lion/input/define';
import { %ValidatorName% } from '@lion/form-core';

Default Validators

By default, the validate system ships with the following validators:

  • Required
  • String Validators, IsString, EqualsLength, MinLength, MaxLength, MinMaxLength, Pattern
  • Number Validators, IsNumber, MinNumber, MaxNumber, MinMaxNumber
  • Date Validators, IsDate, MinDate, MaxDate, MinMaxDate, IsDateDisabled
  • Email Validator, IsEmail

All validators return false if the required validity state is met.

All validators are considered self explanatory due to their explicit namings.

npm i --save @lion/validate-messages
import { loadDefaultFeedbackMessages } from '@lion/validate-messages';

Once the method loadDefaultFeedbackMessages is called, it will make sure that all validators provided in @lion/form-core will have a default error message. It uses the @lion/localize system to provide these translations and has support for more than 15 locales.

Required

The required validator can be put onto every form field element and will make sure that element is not empty. For an input that may mean that it is not an empty string, while for a checkbox-group it means at least one checkbox needs to be checked.

String Validators

Useful on input elements it allows to define how many characters can be entered.

Number Validators

Number validations assume that it's modelValue is actually a number. Therefore it may only be used on input that have an appropriate parser/formatter like the input-amount.

Date Validators

Date validators work with real javascript dates. Use them on input-date or input-datepicker.

Email Validator

Override Default Messages

To get default validation messages you need to import and call the loadDefaultFeedbackMessages function once in your application.

Sometimes the default messages don't make sense for your input field. In that case you want to override it by adding a getMessage function to your validator.

Override fieldName

In the scenario that the default messages are correct, but you only want to change the fieldName, this can both be done for a single specific validator or for all at once.

Custom Validators

Here is an example how you can make your own validator and providing the error messages directly within. You can even hard code localization in there if needed or you can use a localization system.

Note that we import an lion-input here as an example of a form control implementing ValidateMixin. We could equally well use lion-textarea, lion-select, lion-fieldset etc. to illustrate our example.

The custom IsInitialsExample checks if the value is fitting our regex, but does not prevent the user from submitting other values.

Retrieving validity states is as easy as checking for:

myInitialsInput.hasFeedbackFor.include('error');

Validation Examples

Checkbox Validator

You can apply validation to the <lion-checkbox-group>, similar to how you would do so in any fieldset. The interaction states of the <lion-checkbox-group> are evaluated in order to hide or show feedback messages.

Below is a more advanced validator on the group that evaluates the children checkboxes' checked states.

Radio Validator

You can also create a validator that validates whether a certain option is checked.

Combobox

Validation can be used as normal, below is an example of a combobox with a Required validator.

Validation Types

The most common use case for validation is the assessment of whether the input is in error state. An error state would be considered blocking: it prevents a form from being submitted to the server.

However, the validation system also supports three non blocking validation feedback types. Summed up, we have the following four types:

  • error: blocking the field from being submitted to the server. For example: "Please enter an amount higher than 1000,00 euro."
  • warning: something looks wrong, but it is not blocking. For example an optional email input: "Please enter a valid e-mail address in the format "name@example.com"."
  • info: shows extra information. For example a message of a scheduled payment planner: "Ends on 15/05/2020 after 5 payments."
  • success: will only be triggered if there was a Message from one of the above validation types and is now correct. For example: "Ok, correct."

The api for warning validators and info validators are as follows:

Success validators work a bit differently. Their success state is defined by the lack of a previously existing erroneous state (which can be an error or warning state).

So, an error validator going from invalid (true) state to invalid(false) state, will trigger the success validator.

Asynchronous validation

By default, all validations are run synchronously. However, for instance when validation can only take place on server level, asynchronous validation will be needed.

You can make your async validators as follows:

Dynamic parameter change

Disabled inputs validation

According to the W3C specs, Disabled fields should not be validated. Therefore if the attribute disabled is present on a lion-input it will not be validated.

Backend validation

Backend validation is needed in some cases. For example, you have a sign up form, the username could be already taken. You can add an AsyncValidator to check the availability when the username field is changed but you may have a conflict when you submit the form (another user take the username in parallel).