85 lines
2.6 KiB
JavaScript
85 lines
2.6 KiB
JavaScript
import { Controller } from '@hotwired/stimulus'
|
|
import { useFetch } from '../mixins/use_fetch'
|
|
import Autocomplete from '@trevoreyre/autocomplete-js'
|
|
|
|
export default class extends Controller {
|
|
|
|
static targets = [ 'input', 'field', 'resetButton', 'searchIcon' ]
|
|
|
|
static values = { url: String, choices: Array, selected: Boolean }
|
|
|
|
initialize() {
|
|
useFetch(this)
|
|
}
|
|
|
|
connect() {
|
|
const searchHandler = input => {
|
|
return new Promise(resolve => {
|
|
// Check input minimum length
|
|
if (input.length < 2) {
|
|
return resolve([])
|
|
}
|
|
|
|
// Search choices if provided
|
|
if (this.choicesValue.length > 0) {
|
|
return resolve(this.choicesValue.filter(choice => {
|
|
return -1 !== choice.text.toLowerCase().search(input.toLowerCase())
|
|
}))
|
|
}
|
|
|
|
// Use API otherwise
|
|
let data = { search: input }
|
|
fetch(this.urlValue, { method: 'POST', body: JSON.stringify(data), credentials: 'include' })
|
|
.then(this.checkStatus)
|
|
.then(this.parseJSON)
|
|
.then(data => {
|
|
resolve(data)
|
|
})
|
|
})
|
|
}
|
|
|
|
const submitHandler = result => {
|
|
this.fieldTarget.value = result.value
|
|
this.selectedValue = true
|
|
this.element.dispatchEvent(new CustomEvent('select', {
|
|
detail: { result }
|
|
}))
|
|
}
|
|
|
|
this.autocomplete = new Autocomplete(this.element, {
|
|
search: searchHandler,
|
|
getResultValue: result => result.text,
|
|
submitOnEnter: true,
|
|
onSubmit: submitHandler,
|
|
debounceTime: 250,
|
|
})
|
|
|
|
if (this.fieldTarget.value) {
|
|
this.selectedValue = true
|
|
}
|
|
|
|
// prevent form submission when selecting entry in autocomplete list with enter key
|
|
this.element.addEventListener('keypress', e => {
|
|
if (e.key === 'Enter') {
|
|
e.preventDefault()
|
|
}
|
|
})
|
|
}
|
|
|
|
reset() {
|
|
this.inputTarget.value = null
|
|
this.fieldTarget.value = null
|
|
this.selectedValue = false
|
|
this.element.dispatchEvent(new CustomEvent('reset'))
|
|
}
|
|
|
|
selectedValueChanged() {
|
|
this.resetButtonTarget.classList.toggle('hidden', false === this.selectedValue)
|
|
this.searchIconTarget.classList.toggle('hidden', this.selectedValue)
|
|
}
|
|
|
|
disconnect() {
|
|
this.autocomplete.destroy()
|
|
}
|
|
}
|