To get this working I had to create a hidden field to store the value and hijack the drupal autocompleteselect handler in JavaScript. I added a class check on the autocomplete field to hopefully not disturb other autocompletes. **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; } // override drupal.autocomplete object with custom selectHandler function if(typeof Drupal.autocomplete != "undefined") Drupal.autocomplete.options.select = customSelectHandler; })(jQuery, Drupal); **Form PHP** $form['my_field'] = array( '#type' => 'textfield', '#title' => 'My Field', '#attributes' => [ 'class' => ['MYCUSTOM-autocomplete'], ], '#autocomplete_route_name' => 'mymodule.myfield_autocomplete', '#default_value' => '', ); // field value $form['my_field_value'] = array( '#type' => 'hidden', '#value' => '', // default value can go here ); 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.