# Component validators

**Whenever a value is saved to a Component Repository and whenever a value is retrieved via the `getValue()` method of the Component View Model, the value is automatically validated. Validators are added to the component entry in `etc/loki_components.xml` and are fully extensible.**

## Adding a validator to a component
To add a validator to an component - either a new component or an existing component - create a file `etc/loki_components.xml`, find or add an entry for the component in question and then add a new `<validator/>` tag to it.

```xml
<?xml version="1.0" encoding="UTF-8" ?>
<components xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Loki_Components:etc/loki_components.xsd">
    <component name="loki-components.example">
        <validator name="number" />
    </component>
</components>
```

Let's say that the component value is a string `foobar`, then the string `FOOBAR` will not validate correctly and will not be saved to the repository. Let's say that the string `foobar` has been saved before, then the value will be retrieved via the `ComponentViewModel::getValue()` method and will be fully used. However, validation messages will be sent (by default, local messages).

If the component value is an array, each entry in the array is validated as well.

Because validation could be expensive (by using remote APIs), when a value is saved to the repository and retrieved again by the ViewModel in the same AJAX request, validation only will occur once.

## Existing validators
Validators are identified in the `etc/loki_components.xml` file by their name. This name is declared together with a corresponding validator class via the constructor of the class `Loki\Components\Validator\ValidatorRegistry`.

The following validators exist by default:

- `required`
- `number`
- `positive_number`
- `length`
- `email`
- `date`
- `past_date`

Some validators (like `length`) allow configuration via the XML layout (`minlength`, `maxlength`).

Other modules, like `LokiCheckout_Core`, can add additional validators as well: `password_complexity`, `email_available`, `dob`, `gender`, `postcode`, `iban`, etcetera. And you can add your own custom validators.

## Declaring a new custom validator
To add a new validator, an `di.xml` entry is needed:
```xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Loki\Components\Validator\ValidatorRegistry">
        <arguments>
            <argument name="validators" xsi:type="array">
                <item name="badWords" xsi:type="object">YireoTraining\ExampleComponent\Validator\BadWords</item>
            </argument>
        </arguments>
    </type>
</config>
```

Next, the PHP class `YireoTraining\ExampleComponent\Validator\BadWords` needs to be implementing the `Loki\Components\Validator\ValidatorInterface` interface. This could a bit like the following:

```php
<?php declare(strict_types=1);

namespace YireoTraining\ExampleComponent\Validator;

use Loki\Components\Validator\ValidatorInterface;

class BadWords implements ValidatorInterface
{
    public function validate(mixed $value, ?ComponentInterface $component = null): bool|array
    {
        if (false === is_string($value) || empty($value)) {
            return true;
        }
        
        if (false === str_contains($value, 'fart')) {
            return true;
        }
    
        return [__('Go wash your mouth')];
    }
}
```

And now the validator can be applied:

```xml
<?xml version="1.0" encoding="UTF-8" ?>
<components xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Loki_Components:etc/loki_components.xsd">
    <component name="loki-components.example">
        <validator name="badWords" />
    </component>
</components>
```

## Client-side validation
Client-side validation is not included with the Loki Components package. The Loki Field Components package does offer a client-side validation, which is then heavily extended by the Loki Checkout.

See [Client-side validation of Field Components](/field-components/client-side-validation)
