Problem/Motivation

Sometimes want to restrict matching autocomplete to strings that match only at the beginning, not anywhere.
Also, the size should be exposed, similar to the text field widget.

Proposed resolution

expose the size, create a match setting, expose it.

Remaining tasks

User interface changes

Yep. As described above: expose the size and match setting and when match is "starts with", the autocomplete will only match terms that match at the beginning.

Defaults on field edit tab:
tax-defaults-2012-12-24_0100.png

API changes

yes. add parameters for passing the entity and bundle to taxonomy_autocomplete() like:
function taxonomy_autocomplete($field_name, $entity_type, $bundle_name) .
[kept the field_name as the first parament.]
so can get the match setting from the instance returned from     $instance = field_info_instance($entity_type, $field_name, $bundle_name);

Original report by @mstrom81

Hi there,

I noticed what is either a bug, or a UX issue with the autocomplete. Let's say the terms I have in the taxonomy are Architecture and Basketball. After typing in "a", you would expect to only see Architecture, however Basketball also shows up. That's because there's an issue with the db query.

Within taxonomy.pages.inc, there's a method called "taxonomy_autocomplete". It has the following db query code:

// Select rows that match by term name.
$tags_return = $query
->fields('t', array('tid', 'name'))
->condition('t.vid', $vids)
->condition('t.name', '%' . db_like($tag_last) . '%', 'LIKE')
->range(0, 10)
->execute()
->fetchAllKeyed();

The issue is with the following line:
->condition('t.name', '%' . db_like($tag_last) . '%', 'LIKE')

It's looking for LIKE %tag_last%, where it should be looking for LIKE tag_last%.
->condition('t.name', db_like($tag_last) . '%', 'LIKE')

For most use cases I've seen of autocomplete, it looks for terms beginning with whatever the user entered. It seems that most people wouldn't be used to the functionality of autocomplete as-is in this widget.

Any thoughts?

Files: 
CommentFileSizeAuthor
#43 1120144-43.patch10.96 KBtstoeckler
PASSED: [[SimpleTest]]: [MySQL] 40,157 pass(es).
[ View ]
#43 interdiff-42-43.txt3.28 KBtstoeckler
#42 1120144-42.patch13.3 KBtstoeckler
PASSED: [[SimpleTest]]: [MySQL] 39,847 pass(es).
[ View ]
#29 tax-defaults-2012-12-24_0100.png93 KBYesCT
#29 new-settings-2012-12-24_0104.png29.21 KBYesCT
#29 starts-2012-12-24_0108.png21 KBYesCT
#28 drupal-taxonomy_autocomplete_match_anywhere-1120144-28.patch10.18 KBYesCT
FAILED: [[SimpleTest]]: [MySQL] 50,581 pass(es), 1 fail(s), and 4 exception(s).
[ View ]
#28 interdiff-27-28.txt860 bytesYesCT
#27 drupal-taxonomy_autocomplete_match_anywhere-1120144-27.patch10.29 KBYesCT
PASSED: [[SimpleTest]]: [MySQL] 49,420 pass(es).
[ View ]
#27 interdiff-26-27.txt1.01 KBYesCT
#26 drupal-taxonomy_autocomplete_match_anywhere-1120144-26.patch9.69 KBYesCT
PASSED: [[SimpleTest]]: [MySQL] 49,414 pass(es).
[ View ]
#26 interdiff-24-26.txt1.94 KBYesCT
#24 drupal-taxonomy_autocomplete_match_anywhere-1120144-24.patch9.05 KBYesCT
FAILED: [[SimpleTest]]: [MySQL] 49,428 pass(es), 1 fail(s), and 10 exception(s).
[ View ]
#24 interdiff-21-24.txt6.72 KBYesCT
#21 drupal-taxonomy_autocomplete_match_anywhere-1120144-21.patch3.06 KBYesCT
PASSED: [[SimpleTest]]: [MySQL] 49,440 pass(es).
[ View ]
#21 interdiff-15-21.txt2.75 KBYesCT
#20 text_field_size-2012-12-23_0231.png72.82 KBYesCT
#18 widget-in-edit-2012-12-23_0201.png120.18 KBYesCT
#15 drupal-taxonomy_autocomplete_match_anywhere-1120144-15.patch2.2 KBYesCT
PASSED: [[SimpleTest]]: [MySQL] 49,420 pass(es).
[ View ]
#8 tag-s01-2012-12-18_1114.png96.34 KBYesCT
#5 autocomplete.png8.29 KBxjm

Comments

Category:bug» feature
Status:Needs review» Active

It's not a bug, that's how it's designed to work. Maybe there should be a new option to constrain the autocomplete widget so it matches either at the beginning of the name or anywhere in the name.

Title:Term Reference Autocomplete widget - looks for entered text anywhere in term, not just at the beginning of the termTerm Reference Autocomplete widget - lookup anywhere in term, not just from the beginning
Version:7.x-dev» 8.x-dev

Subscribing - goes against 8.x first.

Title:Term Reference Autocomplete widget - lookup anywhere in term, not just from the beginningTerm Reference Autocomplete widget - match only from beginning of term

Re-titling for clarity.

Title:Term Reference Autocomplete widget - match only from beginning of termTerm Reference Autocomplete widget - match any part of term

The feature request is to match any part of the term, instead of current behaviour which is to match the initial letters only. I do think the option to pick one or the other behaviour would be useful. I have several times copied and modified autocomplete functions mainly because I wanted generalized matching.

StatusFileSize
new8.29 KB

#4: Sorry, I'm confused... the current behavior does match anywhere in the term. The initial post is a request to either match only from the beginning, or weight matches from the beginning first.
autocomplete.png

"anywhere in the term" also includes in the middle of any word, not just the first letter of any word in multi-word terms.

Edit: ah, and yes, initially this issue is about just the beginning of each word, so this seems to work like that anyway. I would personally prefer the possibility to at least configure this to match inside words too, but that might be for a different feature request.

Title:Term Reference Autocomplete widget - match any part of termTerm Reference Autocomplete widget - add option to match only start of term

Sorry, I'm the one who got confused.

StatusFileSize
new96.34 KB

Here is a first try at a suggestion for adding options to the autocomplete for terms.

tag-s01-2012-12-18_1114.png

(the screenshot above is from 7.x, but 8.x is similar. this should be done first in 8.x)

the match anywhere only should show when the drop down is autocomplete.

(OR, should there be a configure link, as eventually each drop down might have some configurable options?)

Here is some related code

from core/modules/node/lib/Drupal/node/Plugin/views/wizard/Node.php

// Add the autocomplete textfield to the wizard.
$form['displays']['show']['tagged_with'] = array(
'#type' => 'textfield',
'#title' => t('tagged with'),
'#autocomplete_path' => 'taxonomy/autocomplete/' . $tag_field_name,
'#size' => 30,
'#maxlength' => 1024,
'#field_name' => $tag_field_name,
'#element_validate' => array('views_ui_taxonomy_autocomplete_validate'),
);

That has "settings" for size of the autocomplete.

Also the whole core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php
which shows

/**
* Plugin implementation of the 'taxonomy_autocomplete' widget.
*
* @Plugin(
*   id = "taxonomy_autocomplete",
*   module = "taxonomy",
*   label = @Translation("Autocomplete term widget (tagging)"),
*   field_types = {
*     "taxonomy_term_reference"
*   },
*   settings = {
*     "size" = "60",
*     "autocomplete_path" = "taxonomy/autocomplete",
*     "placeholder" = ""
*   },
*   multiple_values = TRUE
* )
*/

Seems like we can add a setting like "match_anywhere" = TRUE,

Side thought. are there other settings that might want to be set? like size of the text field?

while working on this, I found this error in saving any widget select form. #1872786: Can't change widget types

If we have the match "starts with" it will allow us to use the HTML5 datalist form thing. Which would be nice.

would it be more clear to have a checkbox "match anywhere" where being checked means match anywhere and not being checked means "match starts with" ?

OR

have two radio buttons:
match anywhere (default)
match starts with

?

Also, I dont know very much about plugins or widgets, from a code perspective:

Would this be better as

I. the same autocomplete widget, but exposing some of the "settings", as suggested above with a checkbox, or 2 radio button choices.

Or
II. making a different autocomplete widget, to make a total of 4 choices in the tags widget choice, adding "Autocomplete term widget (tagging) match starts with"

?

I'm guessing I. But I'm having trouble coding it up.

Status:Active» Needs review
StatusFileSize
new2.2 KB
PASSED: [[SimpleTest]]: [MySQL] 49,420 pass(es).
[ View ]

Well, for now, I'm thinking that just unchecking a "match anywhere" is not obvious to be "starts with". so trying to go with radio buttons.

Here is just a start. I still do not know how to get at the widget setting, or how to expose the widget settings form.

For reference I looked at the user autocomplete in core and that is only matching on the first character. Perhaps it's irrelevant.

<?php
$result
= db_select('users')->fields('users', array('name'))->condition('name', db_like($string) . '%', 'LIKE')->range(0, 10)->execute();
?>

Some comments on patch #15!

  • The default value is broken? I created a autocomplete tagging field for my content type. Then after I applied the patch, neither of the radio buttons were selected by default.
  • Shouldn't this new form element be present in the "Field Settings" tab as opposed to the "Edit" tab for the field?
  • The form element #description is a little hard to understand. Can it be simplified?

StatusFileSize
new120.18 KB

@drupaljoe HA! you found the radio buttons? I could not find them. I was looking in field settings and the widget tab!
I did not even look in edit.

The default value is broken? I created a autocomplete tagging field for my content type. Then after I applied the patch, neither of the radio buttons were selected by default.

Please try applying the patch and then installing. (or maybe clearing the caches)
Here is an example of what I usually do to quickly clear a site and reinstall:

sudo rm -r sites
git checkout sites
drush -y si --account-pass=admin --db-url="mysql://root:root@localhost/d8-git" --site-name=autocomplete-15

Shouldn't this new form element be present in the "Field Settings" tab as opposed to the "Edit" tab for the field?

#1855002: Field Settings tab needs renaming to Global Settings (follow-up to Adding new fields leads to a confusing "Field settings" form) might help a bit.
It says that the field settings tab needs to be renamed global settings.
It also asks for discussion on renaming the edit tab to field settings.
My inability to find the radio buttons, that *I* wrote, would speak toward doing that!

The location these settings appeared might imply that the placeholder (and this) autocomplete match would not be global to everywhere this field is shared.
I find shared fields really hard to consider in terms of the correct behavior without a use case. So if someone could put forth a use case for shared fields and how the widget settings should or should not be shared, that might help.
Is the widget shared with a shared field? If not, that for sure puts these under the edit. (It's a bit hard to test that small part though, because I cannot save the widget tab right now... #1872786: Can't change widget types)

Well, here is a screen capture of the edit tab.
widget-in-edit-2012-12-23_0201.png

The form element #description is a little hard to understand. Can it be simplified?

Yes, the description should totally be clarified, shortened, etc. I wonder if it could even be eliminated with the right title and option word choices.
Suggestions for other description, title, and option choices are very welcome.

I'm assuming that the placeholder and the match setting only show when the autocomplete widget is used. So those would not be on this edit tab with a different widget selected.

So, I think it would help to put them in a "Autocomplete" fieldset, grouped together.

OR

To call them
Autocomplete placeholder
Autocomplete match

But I suspect that that repeating of Autocomplete in their title is not elegant, and would not make sense when the widget settings are used in another setting.
I tried to see what other context these widget settings would show in, and views what the one I thought of, but I got a ton of errors when I tried to add a tags autocomplete exposed filter to an enabled front page view... so I could not test that.

If someone could give steps to reproduce how to see this tags autocomplete in another context, that would be really helpful.

StatusFileSize
new72.82 KB

Since the text field widget exposes the size of the field, I think it makes sense for the autocomplete to do the same thing.

text_field_size-2012-12-23_0231.png

StatusFileSize
new2.75 KB
new3.06 KB
PASSED: [[SimpleTest]]: [MySQL] 49,440 pass(es).
[ View ]

I added some comments near the @todo with wild guesses for how to access the widget match setting.

Next step: getting hints or an actual way of accessing that, to get this to work.

Also, I added the field size, after we get this working, we can take that out and make a separate issue to add it in if that is needed. I modified the title to sort of make it clear that we are dealing with autocomplete settings without repeating "autocomplete" in each title.

+++ b/core/modules/taxonomy/taxonomy.pages.incundefined
@@ -140,11 +140,27 @@ function taxonomy_autocomplete($field_name) {
+    // @todo Get the match anywhere value from the field widget setting.
+    // $match = $field->getWidget->getSetting('match');
+    // $match = drupal_container->get('something')->createInstance['widget']['settings']['match'];

Here is the wild guess part.

What you need is to pass an entity and a bundle besides the field name to taxonomy autocomplete so that you can retrieve the instance.

StatusFileSize
new6.72 KB
new9.05 KB
FAILED: [[SimpleTest]]: [MySQL] 49,428 pass(es), 1 fail(s), and 10 exception(s).
[ View ]

This tries to send the entity and bundle every time. I wonder if I can do this though, because maybe the vocabulary is used across entities or bundles.

Also, this is not working: [edit: I forgot to reinstall, so the reason it is not working is different] there is no autocomplete... in the autocomplete field. I'll take a break for a while...

Status:Needs review» Needs work

The last submitted patch, drupal-taxonomy_autocomplete_match_anywhere-1120144-24.patch, failed testing.

Status:Needs work» Needs review
StatusFileSize
new1.94 KB
new9.69 KB
PASSED: [[SimpleTest]]: [MySQL] 49,414 pass(es).
[ View ]

with help from chx to point out the cause of the fail...

but still need to look at why it's not autocomplete anymore.

StatusFileSize
new1.01 KB
new10.29 KB
PASSED: [[SimpleTest]]: [MySQL] 49,420 pass(es).
[ View ]

ah ha. found where the widget itself was needing the additional arguments. now the autocomplete is back.

Issue tags:+Needs tests
StatusFileSize
new860 bytes
new10.18 KB
FAILED: [[SimpleTest]]: [MySQL] 50,581 pass(es), 1 fail(s), and 4 exception(s).
[ View ]

oops. forgot to uncomment the actual implementation that pays attention to the match setting. this does that.
So! this is ready for review.

Next steps:

  • needs tests
  • review

To test:

  1. apply patch and fresh install
  2. create an article with a tag like "one" (OR add a term "one" to the tags vocabulary)
  3. create another article with a tag like "another one" (OR add a term "another" to the tags vocabulary)
  4. create an article, type "one" in the autocomplete and see two tags: "one" and "another one"
  5. edit the tags field on article and pick the starts with match setting.
  6. create an article, type "one" in the autocomplete and see only one tag (matching starts with) "one"

Title:Term Reference Autocomplete widget - add option to match only start of termTerm Reference Autocomplete widget - add option to match only start of term and expose settings (size, match)
StatusFileSize
new21 KB
new29.21 KB
new93 KB

edit the field, shows the size and match (in addition to the placeholder) widget setting

tax-defaults-2012-12-24_0100.png

If change settings to size 20, placeholder "type tags", match "starts with" and follow the steps to test, where tags "one" and "another one" exist.

new-settings-2012-12-24_0104.png

only see "one" since setting is "starts with"

starts-2012-12-24_0108.png

I'll update the issue summary.

Status:Needs review» Needs work

The last submitted patch, drupal-taxonomy_autocomplete_match_anywhere-1120144-28.patch, failed testing.

JFTR
The error message from the test bot:

Drupal\taxonomy\Tests\TermTest
Undefined index: match taxonomy.pages.inc 149 taxonomy_autocomplete()

@drupaljoe (#16)

Thanks for the pointer! JFTR the corresponding code in taxonomy.pages.inc (D7) is:

<?php
// Select rows that match by term name.
   
$tags_return = $query
     
->fields('t', array('tid', 'name'))
      ->
condition('t.vid', $vids)
      ->
condition('t.name', '%' . db_like($tag_last) . '%', 'LIKE')
      ->
range(0, 10)
      ->
execute()
      ->
fetchAllKeyed();
?>

So it's just the additional "%" in the condition which makes the input match elsewhere as only the start of the string.

Right, see the variable: $condition_pattern in the patch.

But @nod_ in #12:

If we have the match "starts with" it will allow us to use the HTML5 datalist form thing. Which would be nice.

I'm not sure if we want to do that here, or in a follow-up... since I'm not sure exactly what "using" that means exactly.

Assigned:Unassigned» YesCT

I think I'll try this again later tonight. I might know more now than I did last time I tried. :)
I'll also go for a follow-up for the html5 concern since no-one felt strongly one way or the other.

Status:Needs work» Needs review
Issue tags:-Needs tests

Status:Needs review» Needs work
Issue tags:+Needs tests

The last submitted patch, drupal-taxonomy_autocomplete_match_anywhere-1120144-28.patch, failed testing.

custom taxonomy stuff might be going away in #1847596: Deprecate Taxonomy term reference field in favor of Entity-reference

how would that effect the ability to do this in 7.x?

the fail in EditorSelection looks like a random failure to me, as that test passed locally.

for my curiosity, how do I get the settings 'match' index declared? adding match to the plugin in the comments did seem to do it.

I want to use index 'match' like: $match = $instance['widget']['settings']['match'];
in core/modules/taxonomy/taxonomy.pages.inc

I thought some magic in core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php
adding match to settings in the plugin definition would take care of that.

but it is not enough because getting the warning:
"Drupal\taxonomy\Tests\TermTest Undefined index: match taxonomy.pages.inc 149 taxonomy_autocomplete()"

Where can I look for how to use/modify plugins?

+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.phpundefined
@@ -35,12 +36,32 @@ class TaxonomyAutocompleteWidget extends WidgetBase {
+      '#type' => 'radios',
+      '#title' => t('Match'),
+      '#default_value' => $this->getSetting('match'),
+      '#options' => array(
+        'anywhere' => t('Anywhere'),
+        'start' => t('Starts with'),
+      ),
+      '#description' => t('Where the autocomplete matches values: either anywhere, or only at the beginning of a term.'),

I'd prefer to see this setting as Checkbox according core UI suggestions

+++ b/core/modules/taxonomy/taxonomy.pages.incundefined
@@ -140,11 +144,25 @@ function taxonomy_autocomplete($field_name) {
+    $match = $instance['widget']['settings']['match'];
+    switch ($match) {
+      case 'start':
+        $condition_pattern = db_like($tag_last) . '%';
+        break;
+
+      case 'anywhere':
+      default:
+        $condition_pattern = '%' . db_like($tag_last) . '%';
+        break;
+    }

This would be simple if() else {}

da_wehner seemed to think it could be done with something to do with views.

I'll keep my eye on that, and try and get it in as part of views conversion.

Version:8.x-dev» 7.x-dev

In fact we can move this issue to 7.x directly. Even though the taxonomy term reference does not support this feature currently, the generic entity reference does. See \Drupal\entity_reference\Plugin\field\Widget\AutocompleteWidgetBase::settingsForm(). And as @YesCT posted, the taxonomy reference is being deprecated in favor of just that.

I will re-roll the patch for 7.x in a minute.

StatusFileSize
new13.3 KB
PASSED: [[SimpleTest]]: [MySQL] 39,847 pass(es).
[ View ]

Here we go. I added some tests for the taxonomy itself but we should also test the widget settings form. Maybe we could get some feedback on the backportability. I think as the strings added (not modified!) here are in Drupal 8 it would seem like a sensible choice IMO.

Oh, and I just now saw that this is still assigned to YesCT. Sorry, if you were working on this. I really gotta check that more often...

Status:Needs work» Needs review
StatusFileSize
new3.28 KB
new10.96 KB
PASSED: [[SimpleTest]]: [MySQL] 40,157 pass(es).
[ View ]

This time with less debug and less commented out test methods.

Also some notes for reviewers:
* I directly used the code that is in the entityreference autocomplete in D8. Therefore this patch should be basically immune to UI reviews, as anything that isn't OK with this UI should be fixed in D8 first in a separate issue.
* I also changed the form values, form API keys, etc. to match those in D8. In D8 the values match the EntityQuery operators, which don't exist in that form in D7, but I don't see any reason to change them to anything else.
* Because it was impossible to actually re-roll this, I had to more or less re-write (or actually re-copy-paste) this from scratch. Therefore I took the liberty of changing a few trivial things. Most noticable is that I changed the URL to be $entity_type/$field_name/$bundle, because field_info_instance() is called in that order. And conceptually we're passing instance information, it's just that instances have no unique identifiers in D7.

Oh, also: as can be seen in the interdiff, I forgot to change the order of the arguments in the place where the URL is actually requested. Therefore if #42 *passes* comes back green, we need additional tests as it really shouldn't.

Assigned:YesCT» Unassigned

No worries, I was waiting to see how the depreciate went in d8. :)
Unassigning from me.

Status:Needs review» Needs work

needs work per #44

Issue summary:View changes

update issue summary to use issue summary template, clarify remaining tasks, and add screenshot of current fix.