Tutorial

Validators

How to define a validator

cplaceJS validators are defined in an attribute's edit modal on the "validators" tab. They are a mighty tool when modeling prototypes or fixing small issues between releases without the need of deployments. However if not handled and maintained carefully they can easily interfere with pro-code logic and may induce unwanted or confusing behaviour, so awareness of what is done how is advised at any time.

Table of contents
  1. Defining a simple validator
  2. Internationalization
  3. Placeholders
  4. Conclusion

Defining a simple validator

For our example we will implement a simple validator which ensures that we're not giving away any products for free or declare negative prices. Let's pretend we have the product type from the change listener example with its cf.cplace.price attribute (a number to hold the selling price of the article).

Enter the attribute edit mode and navigate to the rightmost validators tab and you can jump right into writing logic. The code gets executed every time the corresponding attribute changes. This can be triggered by other change listeners as well so take care to not create feedback loops.

As we want to check if the price is zero or below let's just get the attribute value from the page binding:

var price = page.get('cf.cplace.price');

and then check if it is less than 0 and return an error message in that case

if (price <= 0) {
    return 'Price must be > 0!';
}

This is basically it. But as "basically" implies there's room for improvements:

Internationalization

We can make use of the validator internationalization mechanics which enable us to easily feed mutliple, language dependant error messages to the validator depending on the error-case we create. To do so, we first need to create a message. This is done on the "cplaceJS" tab of the type definition. Here you can click the "New message" button and enter a name for the message as well as localized values.

Note: The names of the messages have to be unique inside of one type definition.

As we also want to split up cases we'll create two messages

lessEqualsZero :
German : 'Wert {0} ist ung├╝ltig. Bitte einen Wert > 0 eingeben'
English: 'Value {0} is invalid. Please provide a value > 0'

and

nullValue :
German : 'Feld kann nicht leer sein!'
English: 'Field cannot be empty!'

You can use the provided messages binding to access these messages and retrieve a message by calling messages.get(messageName). So let's enhance our validator and let the user know that we don't allow null values:

if (price === null) {
    return messages.get('nullValue');
}

Placeholders

You may noticed the {0} in the lessEqualsZero message with which we can also use placeholders in messages. The {0} will be substituted with whatever we provide as additional parameters to the messages.get() method like messages.get(name, value_0, value_1, value_2) where value_0 will be mapped to {0}, value_1 to {1} and so forth. Knowing this we can now spice up the validation for values greater than zero and provide a more detailed error message to the user:

if (price <= 0) {
    return messages.get('lessEqualsZero', price);
}

If the user now enters an invalid value like -10.0 this will then be rendered as

Value -10.0 is invalid. Please provide a value > 0

Conclusion

If everything is fine and no invalidation check has failed we return null to indicate that the data is valid.

So in the end we should have a validator which distinguishes between different error cases and displays messages depending on the entered value and which looks like this

var price = page.get('cf.cplace.price');
if (price === null) {
    return messages.get('nullValue');
}
if (price <= 0) {
    return messages.get('lessEqualsZero', price);
}
return null;