feat: htmx powered requests, improved loading indicator
feat: loading indicator and htmx form submit
This commit is contained in:
@@ -1,12 +1,81 @@
|
||||
import { Controller} from '@hotwired/stimulus'
|
||||
import {Controller} from '@hotwired/stimulus'
|
||||
|
||||
export default class extends Controller {
|
||||
|
||||
static targets = [ 'indicator' ]
|
||||
static classes = [ 'hidden' ]
|
||||
static targets = ['indicator']
|
||||
static classes = ['hidden']
|
||||
|
||||
connect() {
|
||||
this.isVisible = false
|
||||
this.debounceTimeout = null
|
||||
|
||||
// Bind event handlers to preserve context
|
||||
this.boundHandleBeforeRequest = this.handleBeforeRequest.bind(this)
|
||||
this.boundHandleAfterRequest = this.handleAfterRequest.bind(this)
|
||||
|
||||
// Listen to HTMX events
|
||||
document.body.addEventListener('htmx:beforeRequest', this.boundHandleBeforeRequest)
|
||||
document.body.addEventListener('htmx:afterRequest', this.boundHandleAfterRequest)
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
// Clean up event listeners
|
||||
document.body.removeEventListener('htmx:beforeRequest', this.boundHandleBeforeRequest)
|
||||
document.body.removeEventListener('htmx:afterRequest', this.boundHandleAfterRequest)
|
||||
|
||||
// Clear any pending timeout
|
||||
if (this.debounceTimeout) {
|
||||
clearTimeout(this.debounceTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
handleBeforeRequest(event) {
|
||||
// Don't start a new debounce if already visible
|
||||
if (this.isVisible) {
|
||||
return
|
||||
}
|
||||
|
||||
// Show indicator after 200ms delay for field refreshes
|
||||
this.debounceTimeout = setTimeout(() => {
|
||||
this.show()
|
||||
}, 200)
|
||||
}
|
||||
|
||||
handleAfterRequest(event) {
|
||||
// Clear debounce timer if request completes before 200ms
|
||||
if (this.debounceTimeout) {
|
||||
clearTimeout(this.debounceTimeout)
|
||||
this.debounceTimeout = null
|
||||
}
|
||||
|
||||
// Check if response contains HX-Redirect header
|
||||
const xhr = event.detail.xhr
|
||||
const hxRedirect = xhr.getResponseHeader('HX-Redirect')
|
||||
|
||||
// Keep loading indicator visible if redirecting
|
||||
if (hxRedirect) {
|
||||
// Ensure indicator is visible during redirect
|
||||
if (!this.isVisible) {
|
||||
this.show()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Hide indicator if it's visible
|
||||
this.hide()
|
||||
}
|
||||
|
||||
show() {
|
||||
this.isVisible = true
|
||||
this.indicatorTarget.classList.remove(this.hiddenClass)
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.isVisible = false
|
||||
this.indicatorTarget.classList.add(this.hiddenClass)
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.indicatorTarget.classList.remove(this.hiddenClass)
|
||||
this.element.scrollIntoView({ block: 'start', behavior: 'smooth'})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user