Skip to content

Commit

Permalink
Add autocomplete stimulus controller
Browse files Browse the repository at this point in the history
This allows us to specify `data-module="autocomplete"` on a `<select>`
element to enhance it to an autocompleteapp/javascript/controllers/autocomplete_controller.js.
  • Loading branch information
tvararu committed Sep 27, 2024
1 parent e35c046 commit e32c1af
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 0 deletions.
60 changes: 60 additions & 0 deletions app/javascript/controllers/autocomplete_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Controller } from "@hotwired/stimulus";
import accessibleAutocomplete from "accessible-autocomplete";

const enhanceOption = (option) => {
return {
name: option.label,
append: option.getAttribute("data-append"),
hint: option.getAttribute("data-hint"),
};
};

const suggestion = (value, options) => {
const option = options.find(({ name }) => name === value);
if (option) {
const html = option.append ? `${value}${option.append}` : value;
return option.hint
? `${html}<br><span class="autocomplete__option-hint">${option.hint}</span>`
: html;
} else {
return "No results found";
}
};

const autocomplete = ($module) => {
if (!$module) {
return;
}

const params = $module.dataset;

const selectOptions = Array.from($module.options);
const options = selectOptions.map((option) => enhanceOption(option));

accessibleAutocomplete.enhanceSelectElement({
autoselect: params.autoselect === "true",
defaultValue: params.defaultValue || "",
displayMenu: params.displayMenu,
minLength: params.minLength ? parseInt(params.minLength) : 0,
selectElement: $module,
showAllValues: params.showAllValues === "true",
showNoOptionsFound: params.showNoOptionsFound === "true",
templates: {
suggestion: (value) => suggestion(value, options),
},
onConfirm: (value) => {
const selectedOption = [].filter.call(
selectOptions,
(option) => (option.textContent || option.innerText) === value,
)[0];
if (selectedOption) selectedOption.selected = true;
},
});
};

// Connects to data-module="autocomplete"
export default class extends Controller {
connect() {
autocomplete(this.element);
}
}
3 changes: 3 additions & 0 deletions app/javascript/controllers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

import { application } from "./application";

import AutocompleteController from "./autocomplete_controller";
application.register("autocomplete", AutocompleteController);

import AutosubmitController from "./autosubmit_controller";
application.register("autosubmit", AutosubmitController);

Expand Down

0 comments on commit e32c1af

Please sign in to comment.