e23b871172
Problem:
When pressing Enter in the search input field, focus was lost after
the form was submitted and the Turbo Frame updated with search results.
This forced users to click back into the field to continue interacting
with the search.
Solution:
Added a turbo:frame-load event listener in the bar controller's
showModalAndSubmit method that automatically restores focus to the
search input after the Turbo Frame finishes loading the results.
The listener uses {once: true} to auto-cleanup after execution.
82 lines
1.8 KiB
JavaScript
82 lines
1.8 KiB
JavaScript
import { Controller } from "@hotwired/stimulus"
|
|
import { post } from "@rails/request.js"
|
|
import { nextFrame } from "helpers/timing_helpers";
|
|
|
|
export default class extends Controller {
|
|
static targets = [ "turboFrame", "search", "searchInput", "form", "buttonsContainer" ]
|
|
static outlets = [ "dialog" ]
|
|
static values = {
|
|
searchUrl: String,
|
|
}
|
|
|
|
dialogOutletConnected(outlet, element) {
|
|
outlet.close()
|
|
this.#clearTurboFrame()
|
|
}
|
|
|
|
reset() {
|
|
this.dialogOutlet.close()
|
|
this.#clearTurboFrame()
|
|
|
|
this.#showItem(this.buttonsContainerTarget)
|
|
this.#hideItem(this.searchTarget)
|
|
}
|
|
|
|
clearInput() {
|
|
if (this.searchInputTarget.value) {
|
|
this.searchInputTarget.value = ""
|
|
this.searchInputTarget.focus()
|
|
} else {
|
|
this.reset()
|
|
}
|
|
}
|
|
|
|
showModalAndSubmit(event) {
|
|
this.showModal()
|
|
this.formTarget.requestSubmit()
|
|
|
|
// Restore focus to search input after turbo frame loads
|
|
this.turboFrameTarget.addEventListener("turbo:frame-load", () => {
|
|
this.searchInputTarget.focus()
|
|
}, { once: true })
|
|
}
|
|
|
|
showModal() {
|
|
this.dialogOutlet.open()
|
|
}
|
|
|
|
search(event) {
|
|
this.#showItem(this.searchTarget)
|
|
this.#hideItem(this.buttonsContainerTarget)
|
|
|
|
if (this.searchInputTarget.value.trim()) {
|
|
this.showModalAndSubmit()
|
|
} else {
|
|
this.#loadTurboFrame()
|
|
}
|
|
}
|
|
|
|
#loadTurboFrame() {
|
|
this.turboFrameTarget.src = this.searchUrlValue
|
|
}
|
|
|
|
#clearTurboFrame() {
|
|
this.turboFrameTarget.removeAttribute("src")
|
|
this.turboFrameTarget.innerHtml = ""
|
|
}
|
|
|
|
async #showItem(element) {
|
|
element.removeAttribute("hidden")
|
|
|
|
const autofocusElement = element.querySelector("[autofocus]")
|
|
|
|
autofocusElement?.focus()
|
|
await nextFrame()
|
|
autofocusElement?.select()
|
|
}
|
|
|
|
#hideItem(element) {
|
|
element.setAttribute("hidden", "hidden")
|
|
}
|
|
}
|