Skip to content

use both label and value in lookup autocomplete - #1860

Open
peterjanssens wants to merge 1 commit into
collectiveaccess:dev/2.0from
libis:feat/lookup_autocomplete_labels
Open

use both label and value in lookup autocomplete#1860
peterjanssens wants to merge 1 commit into
collectiveaccess:dev/2.0from
libis:feat/lookup_autocomplete_labels

Conversation

@peterjanssens

Copy link
Copy Markdown
Contributor

The CA implementation of the jQuery autocomplete lookup field is sort of incomplete and in a way backwards, in that the autocomplete element allows both label and value options. https://api.jqueryui.com/autocomplete/#:~:text=The%20label%20property%20is%20displayed,into%20the%20input%20element

"Label" was intended to go in the lookup results, "value" used as the elements real value upon user selection.
This allows that the "suggestions/results" can be a bit more verbose (provide context information for proper selection, especially useful when the results are hard to disambigue), than the actual value you want to store for the item.
It is allowed to only use (either) one, and in that case the jQuery element handles them idempotent.

But having them both is super useful, and we use them alot in our informationservices. When you search for my (regionally quite common) name in Wikidata, you get at least three namesakes and then it helps to differ them, not only by Q12345 as the wiki-identifier, but perhaps descriptions (composer, researcher, photographer) or year of birth,... while not having that metadata in the actual stored label (value: 'Peter Janssens').

Another example is "Catalogue of Life" where metadata reveals in what dataset the occurrence is found, with what taxon id, status of the term (accepted, provisionally, archived,,..)
image
After selection the plain label is kept as the value label (and that other metadata can be stored in detail in the extra info if needed/useful; cfr. the dot-style notation PR #1415)

This commit allows to "co-exist" with the current implementation, because proper change would require all informationservices to add or toggle the intent of value and label; and for that there are too many informationservices, and probably many more custom services in users repos.

There is one caveat though, that we stumbled upon later with bulk actions (imports, utils,..) where there is supposed to be one value but there is no user 'select' that handles the label/value negociation of jQuery itself.
We need to handle those ourselves by sniffing where we are (import, util/cli) and swap the value, otherwise the value is empty and then gets the label (with the added metadata).

We can keep this change local, but still wanted to share because it makes the informationservices more powerful.
Also want to use this PR to "check the pulse" on the upcoming v3.x, where you mentionned UI changes; if that would be dropping jQuery that makes this remark shortlived :p

@collectiveaccess

Copy link
Copy Markdown
Owner

This is great. Thank you! However, to confirm, you know there are places where this is a breaking change but have not addressed them?

@peterjanssens

peterjanssens commented Feb 18, 2026

Copy link
Copy Markdown
Contributor Author

This feature is non-breaking at first, for everything that exists now (both scenarios old/new can co-exist).
They can become "breaking" when you would indeed setup the "improved" lookup results like

$va_items[$some_key] = array(
'label' => $accepted_label . $with_some_metadata_html
'idno' => $id,
'url' => $url,
'value'=>$accepted_label
);

the exception (and only if you would ever go via bulk operations) would then be something handled late in lookup() like

/* sort of hackish fix for : "label for UI, value for storage" */
if(sizeof($va_items)==1 && $this->isBulkOperationContext()) {
$va_items[$key ]['label'] = $va_items[$key]['value'];
}

and the isBulkOperationContext() would then be something like

function isBulkOperationContext(): bool
{
/* caUtils */
if(
(isset($_SERVER['SCRIPT_FILENAME']) && strpos($_SERVER['SCRIPT_FILENAME'], 'caUtils') !== false) ||
(isset($_SERVER['PHP_SELF']) && strpos($_SERVER['PHP_SELF'], 'caUtils') !== false) ||
(isset($_SERVER['SCRIPT_NAME']) && strpos($_SERVER['SCRIPT_NAME'], 'caUtils') !== false)
){
return true;
}

$uri = $_SERVER['REQUEST_URI'] ?? '';

/* other bulk paths like MetadataImport */
return (
    strpos($uri, 'MetadataImport') !== false ||
    strpos($uri, 'caUtils') !== false
);

}

You can't just lift on "one result" because you might hit one lookup result through the UI (accidently, or some users like to paste a direct uri there in the UI).
There is maybe a more elegant/helper/better way of knowing there is bulk/direct selection but I'm not (yet) aware of.
We currently have this duplicated on each custom InformationService that uses context info, but it could be shifted up to BaseInformationServicePlugin. For us it's these two that I'm aware of: data import with single result inputs (uri best candidate, some terms), and the reload_service_values in utils. There might be others (don't think so), but worst case scenario would be that the label (with encoded html) makes it to the value (that would be the "breaking-not-really-breaking").

I didn't include the "hack" in the feature because it might obscure things.

@peterjanssens

peterjanssens commented Feb 18, 2026

Copy link
Copy Markdown
Contributor Author

currently label is saved as the value ($t_ca_thing->update/insert), swapping that would be the minimal fix addressing all issues (since this commit duplicates both label and value in case value would not be set yet in the old implementation using label as value)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants