TransWikia.com

Form textfield AJAX validation "deletes" injected services to form

Drupal Answers Asked by Pedro Tentugal on October 26, 2021

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.

One Answer

For anyone running into this problem or AJAX call that fails on the second call intermittently, check the properties used on your AJAX form class for the right access. It seems a trivial thing but change the properties of DInjected services to protected. Refrain from using private as the dependency serialization from Drupal won't be able to get those for caching purposes.

Check this link for more information.

Answered by Pedro Tentugal on October 26, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP