Drupal 8: Creación de campos con Field API (Parte II) Autocomplete

Imagen Drupal 8: Creación de campos con Field API (Parte II) Autocomplete

Drupal 8: Creación de campos con Field API (Parte II) Autocomplete

  • Autor: fjavimartin

  • Fecha de Creación: 04/07/2017

  • Categorías:

    • Drupal,
    • Drupal 8,
    • Field,
    • Field api,
    • Autocomplete,
    • Google,
    • Webservice

Completamos nuestro field recién creado incluyendo autocomplete en el textfield encargado de contener la dirección que procederá de los servicios web de google.

Ya tenemos un field encargado de contener una dirección implementado y funcionando, pero debemos encontrar una manera de que nuestros usuarios introduzcan una dirección correcta.

La solución que trataremos pasará por implementar autocomplete en el textfield encargado de contener la dirección de tal manera que el propio campo ofrezca posibles direcciones al mismo tiempo que el usuario escribe.

1. Implementación de la función para autocomplete

En este punto no vamos a profundizar mucho puesto que ya publicamos un artículo en el que implementamos esta misma función.

Cuando implementamos una función de auto completado en un textfield lo que hacemos es declarar una ruta en el módulo a la que le pasamos el contenido actual del textfield y opcionalmente parámetros, estos datos son tratados y devolvemos un json con las posibles sugerencias.

Comenzamos editando nuestro fichero routing.yml para incluir esta nueva ruta:

address_field.autocomplete_address:
  path: '/address_field/autocomplete_address/{key}'
  defaults:
    _controller: '\Drupal\address_field\Controller\AutoCompleteController::address'
    _format: json
  requirements:
    _access: 'TRUE'

Nuestra ruta de auto completado llamará a una función que realmente será la encargada de procesar los datos recibidos. En nuestro caso, además de enviar el contenido del textfield, también enviaremos el parámetro key que contendrá la clave que necesitaremos para utilizar el servicio web de google.

El siguiente paso será la creación de un controlador que contendrá la función encargada de procesar estos datos.

namespace Drupal\address_field\Controller;

use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;


/**
 * 
 * AutoComplete Controller
 *
 */
class AutoCompleteController extends ControllerBase {
  
  /**
   * Handler for Address AutoComplete.
   */
  public function address(Request $request, $key) {
    // Capturamos contenido textfield
    $input = $request->query->get('q');
    // Inicializamos array resultados
    $results = [];
    // Formamos la solicitud al servicio de google
    $url = 'https://maps.googleapis.com/maps/api/place/autocomplete/json?' .
      'input=' . urlencode($input) .
      '&types=geocode' . 
      '&language=es' .
      '&key=' . $key;
    // Realizamos la solicitud al web service que devolverá un JSON
    $response = file_get_contents($url);
    $json = json_decode($response);
    // Si todo ha ido bien rellenamos array de resultados
    // Si hay algún error devolveremos un array vacío
    if ($json->status == 'OK') {
      foreach ($json->predictions as $key => $item) {
        $results[] = [
            'value' => $item->description,
            'label' => $item->description
        ];
      }
    }
    // Devolvemos resultados
    return new JsonResponse($results);
  }
  
}

Nuestro controlador solamente contiene una función que será la encargada de procesar las solicitudes. Básicamente capturamos el contenido del textfield y la clave del servicio web de google, inicializamos el array que contendrá los resultados de la consulta y realizamos la solicitud a google. Si todo ha ido bien llenamos nuestro array de resultados y lo devolvemos como un json.

No hace falta que esperemos a implementar el auto completado en el formulario para comprobar que este funciona. Simplemente podemos acceder a la url indicada en el fichero routing pasando como parámetro la key del webservice de google y obtendremos las sugerencias que este último nos devuelve.

2. Formulario de configuración en nuestro widget

En el apartado anterior hemos creado la función de auto completado y tenemos que pasarle como parámetro la key del servicio web de google por lo que necesitamos implementar en el widget un formulario para recoger este parámetro.

Empezamos modificando en nuestro widget el método settingsForm:

/**
   * {@inheritdoc}
   */
  
  public function settingsForm(array $form, FormStateInterface $form_state) {
    $elements = [];
    
    $elements['gplaceapikey'] = [
      '#type' => 'textfield',
      '#title' => t('Google Place Key Api'),
      '#default_value' => $this->getSetting('gplaceapikey'),
      '#description' => t('Intro Google Key Api for Google Places Web Service'),
      '#required' => TRUE,
    ];
    
    return $elements;
  }

Simplemente devolvemos un array renderizable con el formulario que utilizaremos para recoger este parámetro.

Implementaremos el método defaultSettings para establecer los valores por defecto:

/**
   * {@inheritdoc}
   */
  public static function defaultSettings() {
    return [
      'gplaceapikey' => 'AIzaSyAzFohLrhJU8iQTmXX7KXl8cVD9-JviEPU',
    ] + parent::defaultSettings();
  }

Por último implementamos el método settingsSummary que devolverá un resumen de la configuración del widget:

/**
   * {@inheritdoc}
   */
  public function settingsSummary() {
    $summary = [];

    $summary[] = t('Google Place Api Key: @gplaceapikey', 
        ['@gplaceapikey' => $this->getSetting('gplaceapikey')]);

    return $summary;
  }

Una vez implementados todos estos métodos nuestro formulario se parecerá a la siguiente imagen:

Drupal 8 - Field API - Formulario Widget

Imagen 1 - Drupal 8 - Field API - Formulario Widget

Y el resumen de la configuración:

Drupal 8 - Resumen configuración widget

Imagen 2 - Drupal 8 - Field API - Resumen configuración

A destacar los siguientes métodos para obtener y fijar los valores de los parámetros de configuración del widget:

$this→getSetting('gplaceapikey');
$this→setSetting(‘gplaceapikey’, ‘valor’);

3. Modificación del formulario del widget

Una vez implementados la función de auto completado y el formulario de configuración solamente nos queda modificar el formulario de nuestro widget para incluir la función de auto completado:

/**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $key = $this->getSetting('gplaceapikey');
    $fieldclass = isset($items[$delta]) ? $items[$delta] : NULL;
    
    $element['address'] = [
        '#type' => 'textfield',
        '#title' => t('Address'),
        '#prefix' => '<div id="field-address">',
        '#suffix' => '</div>',
        '#default_value' => 
          isset($fieldclass) ? $fieldclass->get('address')->getValue() : NULL,       
        '#autocomplete_route_name' => 'address_field.autocomplete_address',
        '#autocomplete_route_parameters' => array('key' => $key),
        '#delta' => $delta,
    ];
    
    $element['latitude'] = [
        '#type' => 'textfield',
        '#title' => t('Address Latitude'),
        '#default_value' => 
          isset($fieldclass) ? $fieldclass->get('latitude')->getValue() : NULL,
    ];
    
    $element['longitude'] = [
        '#type' => 'textfield',
        '#title' => t('Address Longitude'),
        '#default_value' => 
          isset($fieldclass) ? $fieldclass->get('longitude')->getValue() : NULL,
    ];
    
    return $element;
  }

Para poder configurar el autocomplete en un textfield bastará con incluir entre sus propiedades:

'#autocomplete_route_name' => 'address_field.autocomplete_address',
'#autocomplete_route_parameters' => array('key' => $key),

Introduciremos el identificador de la ruta de nuestra función de auto completado y un array con los parámetros que utilicemos.

Nuestro formulario se parecerá a lo siguiente:

Drupal 8 - Field API - Form Autocomplete

Imagen 3 - Drupal 8 - Field API - Form Autocomplete

4. Conclusiones

Prueba superada!!!!! Si hemos seguido todos los pasos habremos implementado auto completado en el campo de texto encargado de contener una dirección facilitando enormemente la introducción de una dirección completa gracias al servicio web de google.

En el próximo artículo modificaremos nuestro formulario para que cuando el usuario introduzca una dirección se actualicen automáticamente los campos de latitud/longitud.

Recursos

http://www.e-quipos.es/blog/drupal-8-creaci%C3%B3n-de-campos-con-field-api

http://www.e-quipos.es/blog/drupal-8-textfield-con-autocomplete-desde-google-place

https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Field%21WidgetBase.php/class/WidgetBase/8.2.x

https://developers.google.com/places/web-service/?hl=es-419

http://www.qed42.com/blog/autocomplete-drupal-8

Todos los Derechos Reservados © 2016

Funciona con Drupal