Building a Drupal Service — Part 2
Follow up on the previous article where we build a service
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.
$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::handleAutocomplete
to 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;
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 !