I'm trying to create a form that has two services injected (for access to an API) and a textfield with an AJAX callback. Here it is:
public function buildForm(array $form, FormStateInterface $form_state) {
$form['vat_number'] = [
'#title' => $this->t('VAT Number'),
'#type' => 'textfield',
'#default_value' => isset($address['vat_number']) ? $address['vat_number'] : '',
'#states' => [
'visible' => [
':input[name="is_business"]' => ['checked' => TRUE],
],
'required' => [
':input[name="is_business"]' => ['checked' => TRUE],
],
],
'#ajax' => [
'callback' => '::validateVatAjax',
'event' => 'change',
'url' => Url::fromRoute('shop_product.digital_river_payment_form'),
'options' => [
'query' => [
FormBuilderInterface::AJAX_FORM_REQUEST => TRUE,
],
],
],
'#suffix' => '</div>',
];
}
.....
}
public function validateVatAjax(array &$form, FormStateInterface $form_state) {$response = new AjaxResponse();
$message = '<div id="errors" class="alert alert-danger" role="alert">';
if (!$this->customerService->validateCustomerTaxFormat($form_state->getValue('vat_number'))) {
$message .= $this->customerService->$schema['properties']['value']['description'];
$message .= '</div>';
}
else {
$message = '<div id="errors" class="alert alert-danger hide" role="alert"></div>';
}
$response->addCommand(new ReplaceCommand('#errors', $message));
$form_state->setRebuild(FALSE);
return $response;
}
public function validateForm(array &$form, FormStateInterface $form_state) {
if ($form_state->getValue('is_business') == 1) {
$vat_number = $form_state->getValue('vat_number');
if (empty($vat_number)) {
$form_state->setErrorByName('vat_number', $this->t('Please enter your tax number.'));
}
elseif (!$this->customerService->validateCustomerTaxFormat($form_state->getValue('vat_number'))) {
$schema = $this->customerService->getSchema();
$form_state->setErrorByName('vat_number', $schema['properties']['value']['description']);
}
else {
$form_state->setErrorByName('vat_number', $this->t('Please enter your VAT number including the two letter country code.'));
}
}
}
}
I omitted some of the code but my problem is that on the second AJAX call to the callback, it fails because the customerService is null. Aside from that, I don't understand why validateForm() is called on the textfield input change. Is this normal for Drupal?
Thanks in advance.
::
, the form callback must be a static function. You cannot use$this->something
in a form callback.call_user_func_array([$this, $method], $arguments)
. Anyway, still need to understand how to persist the DI services in my form class.