Ajax Lifecycle
Events
All events bubble and are cancellable by default.
Bubbling means they will always start from the form / link that submits the event and
continues upward all the way to the top of the DOM. Bubbling can be
stopped via event.stopImmediatePropagation()
. Events are also
cancelable / preventable in the following way:
calling event.preventDefault()
on an ajax event will cause it to stop running.
A form / link with the data-remote="true"
attribute or a link with data-method="<method>"
will fire the following events:
ajax:before
ajax:beforeSend
ajax:send
ajax:request:error # => Error sending the request
ajax:response:error # => 404s, 500s, etc
ajax:error # => will catch both request and response errors.
ajax:success
ajax:complete
ajax:beforeNavigation # => fires before the navigation adapter, can be stopped.
ajax:stopped # => when event.preventDefault() is called or event.detail.fetchRequest.cancel(event) is called.
ujs:beforeMorph
ujs:afterMorph
- Diagram of Ajax form submissions
mrujs-remote-form-event-diagram.pdf
All properties available on event.detail
element // => either form or link element that initiated request
fetchRequest // => FetchRequest (wrapper around Request)
request // => Request
fetchResponse // => FetchResponse (wrapper around Response)
response // => Response
submitter // => The button clicked to initiate the submit. Button / Link element
submission // => Either FormSubmission or MethodSubmission.
status // => available for ajax:success, ajax:complete, ajax:response:error, ajax:error
<a href="#" data-method="delete" data-remote="true">
Link
</a>
does not fire the submit
event, it skips to ajax:before
, this is due to
to the fact that links do not actually trigger a submit
event.
Cancelling Events
Cancelling Ajax events is fairly straightforward with only 1 edge case
involving the ajax:send
event which we will cover below.
We can cancel events at anytime by calling event.preventDefault()
.
Example:
document.querySelector("form").addEventListener("ajax:before", (event) => {
event.preventDefault();
})
ajax:send
is a special case and must be aborted with an abort
controller. To do so, we must do the following:
document.querySelector("form").addEventListener("ajax:send", (event) => {
event.detail.fetchRequest.cancel(event)
})
event.stopImmediatePropagation()
or
event.stopPropagation()
, this will prevent the
ajax:stopped
or ajax:completed
events
from firing and will leave our buttons in a disabled state that we must handle manually.