Autocomplete used on a single value field should not split input on commas

Created on 28 March 2017, over 8 years ago
Updated 16 January 2024, over 1 year ago

Problem/Motivation

When an autocomplete widget is used on a single value field the clientside javascript code treats it as a multivalue field if what is entered by the user contains commas. This results in undesired behavior where only the last value is autocompleted instead of the entire text as entered.

Steps to reproduce

1. Setup a new Autocomplete and set the "allowed number of values" to "1"
2. Type "Pine, Apple, P"

EXPECTED:
Matching tags with text "Pine, Apple, P", for example:
`Pine, Apple, Pine Apple Pen`
`Pine, Apple, Pen`

RESULT:
`Pen`
`Peter`

Proposed resolution

Always search full text in Autocomplete input

Remaining tasks

- Fix it to search full text on Autocomplete input
- Selection on Autocomplete should replace old tag

User interface changes

- TBA

API changes

Yes. Details TBD. But something like:

  1. A new Form API attribute to toggle the split behavior.
  2. A new setting passed into autocomplete.js to toggle the split behavior.

Data model changes

- TBA

Feature request
Status

Active

Version

11.0 🔥

Component
Field 

Last updated 1 day ago

Created by

🇭🇰Hong Kong droplet

Live updates comments and jobs are added and updated live.
  • Usability

    Makes Drupal easier to use. Preferred over UX, D7UX, etc.

Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • First commit to issue fork.
  • 🇸🇮Slovenia alecsmrekar

    I opened this PR with some initial work done on the JS side, it basically just avoids splitting the string if the form element has the data-autocomplete-single attribute.

  • 🇬🇧United Kingdom graham73may

    Facing this exact issue, very glad to see some work has been done on this already, thanks @alecsmrekar

    In my instance my Autocomplete field is replacing only the part of the string *after* the last comma. For example:

    1. Searching for "phrase with, commas".
    2. Select one of the autocomplete results, e.g. "Longer phrase with, commas"
    3. The field value is then set to "phrase with, Longer phrase with, commas".

    Patch in #21 is working for me. After applying the patch and adding the `data-autocomplete-single` attribute to my field the full value is replaced:

    1. Searching for "phrase with, commas".
    2. Select one of the autocomplete results, e.g. "Longer phrase with, commas"
    3. The field value is then set to "Longer phrase with, commas".

  • 🇬🇧United Kingdom scott_euser

    I think that happens in

      function selectHandler(event, ui) {
        const terms = autocomplete.splitValues(event.target.value);
        // Remove the current input.
        terms.pop();
        // Add the selected item.
        terms.push(ui.item.value);
    

    Which should probably become something like this pseudo code:

      function selectHandler(event, ui) {
        const terms = autocomplete.splitValues(event.target.value);
        if ( is single ) {
          // Remove all inputs, the field only allows one selection.
          terms. remove all of them();
        }
        else {
          // Remove the current input only.
          terms.pop();
        }
        // Add the selected item.
        terms.push(ui.item.value);
    
  • 🇬🇧United Kingdom graham73may

    I think Patch #21 already delivers on that change.

    autocomplete.splitValues defined here:
    https://git.drupalcode.org/project/drupal/-/blob/1efbc4ec5b4ccd770e51e77...

    Fires autocompleteSplitValues from here:
    https://git.drupalcode.org/project/drupal/-/blob/1efbc4ec5b4ccd770e51e77...

    Which has the change:

        if (autocomplete.options.isSingle) {
          return value ? [value] : [];
        }
    
  • Status changed to Needs work 12 months ago
  • 🇬🇧United Kingdom scott_euser

    Okay confirm you are saying this is working then already as is with single. So the next step here is to confirm with test coverage. Changing to NW given there is an MR

  • 🇬🇧United Kingdom scott_euser

    Updated issue summary to cover Graham's issue that is also fixed by this.

  • Pipeline finished with Failed
    12 months ago
    Total: 18643110s
    #77990
  • Pipeline finished with Failed
    12 months ago
    Total: 210s
    #257766
  • 🇩🇪Germany Anybody Porta Westfalica

    A client just ran into this, I agree this is confusing UX, especially if you use both: Autocomplete and Tags-Style for different use-cases in the same project.

  • 🇨🇦Canada dan3h

    I've installed the patch from #21 on our Drupal 10.4 site, and it has not resolved the problem.

    I did some debugging, and found that on the Javascript side, everything is handled nicely with the patch in place. It is now returning "Apples, and Bananas" instead of just "and Bananas".

    But on the Drupal side, it's still not working. handleAutocomplete() in html/core/modules/system/src/Controller/EntityAutocompleteController.php looks like this:

      public function handleAutocomplete(Request $request, $target_type, $selection_handler, $selection_settings_key) {
        $matches = [];
        // Get the typed string from the URL, if it exists.
        $input = $request->query->get('q');
        // Check this string for emptiness, but allow any non-empty string.
        if (is_string($input) && strlen($input)) {
          $tag_list = Tags::explode($input);
          $tag_list = [$input];
          $typed_string = !empty($tag_list) ? mb_strtolower(array_pop($tag_list)) : '';
    

    $input starts out as "Apples, and Bananas", but Tags::explode breaks it on the comma, and then $typed_string ends up with only "and Bananas".

    This is the value that is then passed (at the end of that same function) into the matcher, which results in autocomplete results that ignore what came before the comma:
    $matches = $this->matcher->getMatches($target_type, $selection_handler, $selection_settings, $typed_string);

    When I replace $tag_list = Tags::explode($input); with $tag_list = [$input];, it works, for this one autocomplete field I am trying to debug. But of course that removes the multi-term handling functionality for the whole rest of the site.

    I'm not sure how to proceed here. Any ideas?

  • 🇺🇸United States dww

    Re: #29 - Right, that's the basic problem I foretold at #12. The backend needs to know about this, too. If the behavior is to be determined by field cardinality, we need some way for the Field API (which knows about field cardinality) to communicate with the Form API (which handles autocomplete) about how to handle commas.

Production build 0.71.5 2024