Agregar autocompletar para campo de texto

10

Traté de implementar un autocompletado en campo de texto para drupal 8 en mi módulo personalizado

todo lo que quería era buscar y mostrar el probable título que escribí a través de autocompletar, así que declaré una función pública autocompletar dentro de una clase en DefaultController.php en el directorio de la carpeta -> mymodule / src / Controller / DefaultController.php

<?php

namespace Drupal\mymodule\Controller;

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

class DefaultController extends ControllerBase
{
    public function autocomplete($string)
    {
        $matches = array();
        $db = \Drupal::database();
        $result = $db->select('node_field_data', 'n')
        ->fields('n', array('title', 'nid'))
        ->condition('title', '%'.db_like($string).'%', 'LIKE')
        ->addTag('node_access')
        ->execute();

        foreach ($result as $row) {
            $matches[$row->nid] = check_plain($row->title);
        }

        return new JsonResponse($matches);
    }
}

luego creó un EditForm.php en el directorio de la carpeta -> mymodule / src / Form / EditForm.php

<?php

namespace Drupal\mymodule\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

class EditForm extends FormBase
{
    public function getFormId()
    {
        return 'mymodule_edit_form';
    }

    public function buildForm(array $form, FormStateInterface $form_state)
    {
        $form = array();

  $form['input_fields']['nid'] = array(
    '#type' => 'textfield',
    '#title' => t('Name of the referenced node'),
    '#autocomplete_route_name' => 'mymodule.autocomplete',
    '#description' => t('Node Add/Edit type block'),
    '#default' => ($form_state->isValueEmpty('nid')) ? null : ($form_state->getValue('nid')),
    '#required' => true,
  );

        $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Create'),
  );

        return $form;
    }
}

También creó mymodule.routing.yml

  mymodule.autocomplete:
  path: '/mymodule/autocomplete'
  defaults:
    _controller: '\Drupal\mymodule\Controller\DefaultController::autocomplete'
  requirements:
    _permission: 'access content'

¿Todavía no se implementa la funcionalidad de autocompletar? ¿Alguien puede señalarme qué me estoy perdiendo?

hazme vivo
fuente
necesita pasar parámetros también drupal.org/node/2070985
Shreya Shetty
1
@ShreyaShetty No, no necesito parámetros ya que en d7 hubiera usado '#autocomplete_path' => 'mymodule / autocomplete', así que en d8 usé '#autocomplete_route_name' => 'mymodule.autocomplete', así que nunca usé el parámetro ni necesito uno ....
make-me-alive

Respuestas:

10

Su clase necesita alguna modificación, necesita verificar la solicitud y ponerla en $ string.

<?php

namespace Drupal\mymodule\Controller;

use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Drupal\Component\Utility\Unicode;

class DefaultController extends ControllerBase
{

  /**
   * Returns response for the autocompletion.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The current request object containing the search string.
   *
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   *   A JSON response containing the autocomplete suggestions.
   */

  public function autocomplete(request $request) {
    $matches = array();
    $string = $request->query->get('q');
    if ($string) {
      $matches = array();
      $query = \Drupal::entityQuery('node')
      ->condition('status', 1)
      ->condition('title', '%'.db_like($string).'%', 'LIKE');
      //->condition('field_tags.entity.name', 'node_access');
      $nids = $query->execute();
      $result = entity_load_multiple('node', $nids);
      foreach ($result as $row) {
        //$matches[$row->nid->value] = $row->title->value;
        $matches[] = ['value' => $row->nid->value, 'label' => $row->title->value];
      }
    }
    return new JsonResponse($matches);
  }
}
vgoradiya
fuente
todavía NO FUNCIONÓ después de buscar una solicitud y colocarla en $ string
make-me-alive
¿ha verificado que su solicitud fue impresa?
vgoradiya
Creo que \Drupal::entityQuery('node')sería preferible usar aparte de select.
vgoradiya
Después de ver la pestaña Red en las herramientas de desarrollo de mi navegador, pude ver resultados adecuados en la respuesta, pero no se mostraban en la interfaz de usuario. Después de investigar un poco, descubrí que tenía un css personalizado que configuraba un z-indexelemento DOM que contenía el formulario. El valor era demasiado alto y superponía los resultados del autocompletado. Bajar mi costumbre lo z-indexarregló para mí.
tyler.frankenstein
11

Si desea seleccionar una entidad, entonces hay una manera más fácil de hacerlo. Drupal 8 tiene un tipo de campo entidad_autocompleto estándar, solo especifique su elemento de formulario de esta manera:

$form['node'] = [
  '#type' => 'entity_autocomplete',
  '#target_type' => 'node',
];

Consulte Campo personalizado de autocompletar para obtener más información.

Además, nunca haga consultas de bases de datos contra tablas de nodo / entidad. Use \ Drupal :: entityQuery () para eso.

Berdir
fuente
Hola Berdir, ¿Cómo obtener datos de la taxanomía en mi caso "ciudad" usando el código anterior ya que funciona perfectamente bien para el nodo pero no para la taxanomía?
Sachin
5
  1. Cree un archivo routing.yml y agregue el siguiente código: admin_example.autocomplete:

:

  path: '/admin_example/autocomplete'
  defaults:
    _controller: '\Drupal\admin_example\Controller\AdminNotesController::autocomplete'
  requirements:
    _permission: 'access content'
  1. El formulario que ha compilado en mymodule / src / Form / EditForm.php es correcto

Debe cambiar el código en el controlador. El código está a continuación:

public function autocomplete(Request $request)
{
 $string = $request->query->get('q');
    $matches = array();
      $query = db_select('node_field_data', 'n')
          ->fields('n', array('title', 'nid'))
          ->condition('title', $string . '%', 'LIKE')
          ->execute()
          ->fetchAll();
    foreach ($query as $row) {
        $matches[] = array('value' => $row->nid, 'label' => $row->title);
    }

    return new JsonResponse($matches);
}
Shreya Shetty
fuente
Hola Shreya, utilicé tu solución, pero en lugar de ir al formulario, me da o / p de esta manera: [{"value": "1", "label": "Patel Residency"}, {"value": " 2 "," label ":" Jain Plaza "}, {" value ":" 3 "," label ":" Kanha Resort "}, {" value ":" 38 "," label ":" Hira Residency "} ] Quiero que pase al formulario y el campo debería funcionar como autocompletado
Sachin
2

Use el código @vgoradiya y luego en el bucle foreach inténtelo de esta manera:

    foreach ($result as $row)
    {
        $matches[] = ['value' => $row->nid, 'label' => check_plain($row->title)];
    }
Spencer Chang
fuente