Skip to content

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)

New Item

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);
      }
    }
  }

The result