Set a default value dynamically for an Afform field in an extension
The challenge¶
In our extension we want to set a default value for a field on an Afform dynamically. We could in theory achiev this by changing the definition of the Afform but we want to do this in an extension.
The example¶
As an example we will look at the Simple Orders extension and do something to set a default in the new ehplay 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 a default value to the description field in the form. Not really useful but it shows quite well what we want to achieve.
The solution¶
We will add a listener for the hook civi.api.respond (which is not officially documented) and add a static method to process on the event.
Add the listener¶
In the extension the listeners for hooks are added in the ehplay.php file using the ehplay_civicrm_config method. So we will add the listener for civi.api.respond to the list that is already there.
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 ehplay_civicrm_config(\CRM_Core_Config $config): void {
Civi::dispatcher()->addListener('civi.api.respond', ['Civi\Ehplay\HookHandler', 'onApiRespond']);
_ehplay_civix_civicrm_config($config);
}
Add the respond method to set the default¶
We will add the validation method onRespond as specified in the listener to the HookHandler class.
public static function onApiRespond(RespondEvent $event): void {
if ($event->getEntityName() == 'Afform' && $event->getActionName() == 'prefill') {
$apiRequest = $event->getApiRequest();
if ($apiRequest->getName() == 'afformNewItem') {
$response = $event->getResponse();
$response->exchangeArray([
['name' => 'SoItem1', 'values' => [['fields' => ['description' => 'Test by Erik']]]]]);
$event->setResponse($response);
}
}
}