Building a Drupal Service — Part 2

Follow up on the previous article where we build a service

Pasan Gamage
3 min readApr 25, 2024

In case if you want to jump in to the first part, please take a look here.

In continuation from my previous post, I will utilise our address search Drupal service by making it an autocomplete field in a form. This involves only 3 steps.

Step 1 — Create a field

First, we need to create an address field in our form. I’m using the default user registration form for this.

Step 2 — Add a route

Now we need to alter the field using a form alter hook or in my case I’ve already extended the default user registration form. I’ve demonstrated this in a previous article. You can find the code for this in my GitHub repository.

https://github.com/pasankg/d10-playground/blob/develop/web/modules/custom/playground_form/src/Form/NewRegisterForm.php#L25

$form['field_address']['widget'][0]['value']['#autocomplete_route_name'] = 'playground_address_search.autocomplete';

In the above code, we simply follow the Drupal core as an example. We can assign a property #autocomplete_route_name to our Address field field_address and assign it a route. This route will be defined in our routing.yml file

playground_address_search.autocomplete:
path: '/autocomplete/address'
defaults:
_controller: '\Drupal\playground_address_search\Controller\JsonApiAddressController::handleAutocomplete'
_format: json
requirements:
_permission: 'access content'

path will be used by Drupal form API to talk to the controller defined in defaults We will be able to see this Ajax request in the browser network tab.

Do note that we have directly set the controller class name and the method like so JsonApiAddressController::handleAutocompleteto be called when the /autocomplete/address path is requested.

Step 3 — Add a controller

The main logic will be inside the controller class.

Let’s create a controller class named JsonApiAddressController.php under /src/Controller/ directory.

Let’s look at our handleAutocomplete() method.

  /**
* @return JsonResponse
*/
public function handleAutocomplete(Request $request) {
$results = [];
$input = $request->query->get('q');
if (!$input) {
return new JsonResponse($results);
}
if (strlen($input) <= 6) {
return new JsonResponse($results);
}

$input = Xss::filter($input);

// Use Address Search Service.
$service = \Drupal::service('playground_address_search.connection');
$addresses = $service->getAddresses($input);
$isError = gettype($addresses) === 'array' ?? TRUE;

if ($isError && array_key_exists('error', $addresses)) {
return new JsonResponse($results);
}
else {
$list = json_decode($addresses, FALSE);
foreach ($list as $item) {
$results[] = [
'value' => $item->sla,
'label' => $item->sla,
];
}
return new JsonResponse($results);
}
}

}

For demonstration purpose, I’ve limited when to send a request to the RapidAPI from the backend by checking the size of the request query. You may change it as suitable for you.

The important part is that we Xss filter the user input. For this we can use Drupal’s default Xss class web/core/lib/Drupal/Component/Utility/Xss.php

In the two lines after I’ve used our address search service.

$service = \Drupal::service('playground_address_search.connection');
$addresses = $service->getAddresses($input);

Wrap up

When everything is connected together, the final result will look like this;

Note the request path in above screengrab.

You can find the complete module code in my GitHub repository.

https://github.com/pasankg/d10-playground/tree/develop/web/modules/custom/playground_address_search

Hope this series has been helpful for you.

Happy coding !

--

--

Pasan Gamage
Pasan Gamage

Written by Pasan Gamage

Backend Developer | Motorbike enthusiast

No responses yet