Автодополняемые поля Drupal 8

Подключение автодополнения к полю формы подробно описано здесь: http://niklan.net/blog/77

Однако есть момент, которого там не найти.

Если в форме есть несколько полей с однотипным алгоритмом автодополнения, но разными источниками хранения данных, не обязательно делать несколько отдельных функций автодополнения, в функцию автодополнения можно передать дополнительные параметры. В Drupal 7 можно было просто в hook_menu создать страницу с параметром. B варьировать этот параметр при создании формы, задавая #autocomplete_path.

function mymodule_menu() {
  $items['autocomplete/%'] = array(
    'page callback' => 'mymodule_autocomplete',
    'page arguments' => array(1),
  );

  return $items;
}

function mymodule_myform() {
  $form['myfield1'] = array(
    '#type' => 'textfield',
    '#title' => 'My field 1',
    '#autocomplete_path' => 'autocomplete/myfield1', 
  );
  $form['myfield2'] = array(
    '#type' => 'textfield',
    '#title' => 'My field 2',
    '#autocomplete_path' => 'autocomplete/myfield2', 
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Submit',
  );
  return $form;
}

function mymodule_autocomplete($string,$argument) {
  switch($argument){
    case 'myfield1':
      $result = db_select('field1_table', 'n')
        ->fields('n', array('title'))
        ->condition('title', '%' . db_like($string) . '%', 'LIKE')
        ->range(0, 10)
        ->execute();
      $matches = array();
      foreach ($result as $row) {
        $matches[$row->title] = check_plain($row->title);
      }
      break;
    case 'myfield2':
      $result = db_select('field2_table', 'n')
        ->fields('n', array('title'))
        ->condition('title', '%' . db_like($string) . '%', 'LIKE')
        ->range(0, 10)
        ->execute();
      $matches = array();
      foreach ($result as $row) {
        $matches[$row->title] = check_plain($row->title);
      }
      break;
  }
 
  drupal_json_output($matches);
}

В Drupal 8 мы не можем задавать адрес страницы автодополнения напрямую, но используются два других параметра.

1. #autocomplete_route_name - название роута автодополнения

2. #autocomplete_route_parameters - массив с дополнительными параметрами

В итоге получаем следующий код.

В файле с роутами:

ceh.add_mat_autocomplete:
  path: '/matac/{mtype}'
  defaults:
    _controller: '\Drupal\ceh\Controller\CehController::matac'
  requirements:
    _permission: 'view content'

В файле с формой:

  $form['field1'] = [
    '#type' => 'textfield',
    '#title' => $this->t('Field1'),
    '#autocomplete_route_name' => 'ceh.add_mat_autocomplete',
    '#autocomplete_route_parameters' => array('mtype' => 'field1param'),
  ];
  $form['field2'] = [
    '#type' => 'textfield',
    '#title' => $this->t('Field2'),
    '#autocomplete_route_name' => 'ceh.add_mat_autocomplete',
    '#autocomplete_route_parameters' => array('mtype' => 'field2param'),
  ];

В файле с контроллером роута:

  public function matac(Request $request,$mtype){
    $matches = array();
    $string = $request->query->get('q');
    if($string){
      switch($mtype){
        case 'field1param':
          $query = Database::getConnection()->select('field1table', 'n')
            ->fields('n', array('nid', 'title'))
            ->condition('n.title', '%' . $string . '%', 'LIKE')
            ->range(0, 10);
          $result = $query->execute();
          foreach ($result as $row) {
            $value = Html::escape($row->title . ' (' . $row->nid . ')');
            $label = Html::escape($row->title);
            $matches[] = ['value' => $value, 'label' => $label];
          }        
          break;
        case 'field2param':
          $query = Database::getConnection()->select('field2table', 'n')
            ->fields('n', array('nid', 'title'))
            ->condition('n.title', '%' . $string . '%', 'LIKE')
            ->range(0, 10);
          $result = $query->execute();
          foreach ($result as $row) {
            $value = Html::escape($row->title . ' (' . $row->nid . ')');
            $label = Html::escape($row->title);
            $matches[] = ['value' => $value, 'label' => $label];
          }        
          break;
      }
    }
    return new JsonResponse($matches);
  }

 

Источники: 
http://niklan.net/blog/77
https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Render!Element!FormElement.php/function/FormElement%3A%3AprocessAutocomplete/8