Validate an Afform field in an extension
The challenge¶
In our extension we want to validate a field from an form created with FormBuilder.
The example¶
As an example we will look at the Simple Orders extension. In this extension we have a form to add a new item which was built with FormBuilder.
On the form for a new item there are 3 fields: 1. name 2. description 3. type (options, initially with values digital and physical)

We want to add validation that the name that is entered in the form does not already exists for another item.
The solution¶
We will add a listener for the hook civi.afform.validate and add a static method to perform the validation.
Add the listener¶
In the extension the listeners for hooks are added in the simpleorders.php file using the simpleorders_civicrm_config method. So we will add the listener for civi.afform.validate to the list that is already there (and note the priority Events::W_EARLY)
Hook listeners
There are more ways in which you can add a listener for a hook, see the Symfony method documentation
use Civi\API\Events;
function simpleorders_civicrm_config(&$config): void {
Civi::dispatcher()->addListener('civi.afform.validate', ['Civi\Simpleorders\HookHandler', 'onAfformValidate'], Events::W_EARLY);
_simpleorders_civix_civicrm_config($config);
}
Add the validation method¶
We will add the validation method onAfformValidate as specified in the listener to the HookHandler class.
use Civi\Afform\Event\AfformValidateEvent;
public static function onAfformValidate(AfformValidateEvent $event): void {
$values = $event->getSubmittedValues();
if ($values['SoItem1']) {
foreach ($values['SoItem1'][0]['fields'] as $fieldName => $fieldValue) {
if ($fieldName == 'name' && \CRM_Simpleorders_BAO_SoItem::isExistingName($fieldValue)) {
$event->setError(E::ts('Item name already exists in the database'));
}
}
}
}
The result¶
