2

I have a textfield autocomplete field that shows a list of full user names and email addresses as designed but when a user is selected, the user id is displayed in the field; not the name and email address. This is the form element:

$form['people'] = [
  '#type' => 'textfield',
  '#placeholder' => t('Search by name'),
  '#autocomplete_route_name' => 'my_module.people',
];

This is the autocomplete handler in the controller:

public function handleAutocomplete(Request $request) {

  $query = $this->database->select('simplenews_subscriber', 'ss');
  $or = $query->orConditionGroup()
    ->condition('pa.address_given_name', '%' .$request->query->get('q') . '%', 'LIKE')
    ->condition('pa.address_family_name', '%' .$request->query->get('q') . '%', 'LIKE');
  $query->leftJoin('simplenews_subscriber__subscriptions', 'sss', 'sss.entity_id = ss.id');
  $query->leftJoin('profile', 'p', 'p.uid = ss.uid');
  $query->leftJoin('profile__address', 'pa', 'pa.entity_id = p.profile_id');
  $query->fields('ss', ['uid', 'mail']);
  $query->fields('pa', ['address_given_name', 'address_family_name']);
  $query->condition($or);
  $query->orderBy('address_given_name');
  $query->range(0, 10);

  $results = $query->execute()->fetchAll();

  $users = [];

  foreach ($results as $user) {
    $users[] = [
      'value' => $user->uid,
      'label' => $user->address_given_name . ' ' . $user->address_family_name . ' (' . $user->mail . ')',
    ];
  }

  return new JsonResponse($users);
}

The autocomplete textfield populates properly. I just want the first name, last name and email address to show after a selection has been made.

2

You can find an idea in the forum, I also gave a small contribution:

https://www.drupal.org/forum/support/module-development-and-code-questions/2016-02-12/custom-autocomplete-fields-like#comment-12681634

I am convinced that autocomplete suffers from design flaws and I would like to use a customized version, but I don't know how to proceed. In the meantime, the technique outlined in the discussion in the forum could put you on track for a solution.

  • I convinced the client to change requirements to use a select with fewer values but your answer is both relevant and useful so I upvoted it. Thank you! – user320691 Jul 11 '18 at 16:50
0

To get this working I had to create a hidden field to store the value and use a custom selectHandler applied via class.

JavaScript File

(function ($, Drupal) {

  'use strict';

  /**
   * Override drupal selectHandler function
   */
  function customSelectHandler(event, ui) {
    var valueField = $(event.target);
    if($(event.target).hasClass('MYCUSTOM-autocomplete')) {
      var valueFieldName = event.target.name+'_value';
      if($('input[name='+valueFieldName+']').length > 0) {
        valueField = $('input[name='+valueFieldName+']');
        // update the labels too
        const labels = Drupal.autocomplete.splitValues(event.target.value);
        labels.pop();
        labels.push(ui.item.label);
        event.target.value = labels.join(', ');
      }
    }
    const terms = Drupal.autocomplete.splitValues(valueField.val());
    // Remove the current input.
    terms.pop();
    // Add the selected item.
    terms.push(ui.item.value);

    valueField.val(terms.join(', '));
    // Return false to tell jQuery UI that we've filled in the value already.
    return false;
  }

  Drupal.behaviors.myCustomAutocomplete = {
    attach: function(context, settings) {
      // attach custom select handler to fields with class
      $('input.MYCUSTOM-autocomplete').autocomplete({
        select: customSelectHandler,
      });
    }
  };

})(jQuery, Drupal);

Form PHP

$form['my_field'] = array(
  '#type' => 'textfield',
  '#attributes' => ['class' => ['MYCUSTOM-autocomplete'],],
  '#autocomplete_route_name' => 'mymodule.myfield_autocomplete',
);
// field value
$form['my_field_value'] = array(
  '#type' => 'hidden',
);

On our forms we also have an AJAX callback on the autocompleteselect event, and I've noticed the value for the hidden field is blank but the userInput on the $form_state has the value.

Problem with this is the splitValues function may not work well for the labels, since it appears to be comma-delimited. You may want to write your own to handle it. It also won't work well if using the same form twice on a page, but there may be a way to narrow down the selector on the hidden field.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.