Triggering Turbo Frame with JS

Hey - so I am working on a project where I wanted to trigger a turbo-frame refresh programmatically as well. I did some serious source code diving and hopefully I can help!

With regards to the programmatic form submission:

Turbo intercepts form submission events, but weirdly, the JS formElement.submit() method does not trigger the submit event. Confusing for sure - but the MDN docs lay it out:

The event is not sent to the form when calling the form.submit() method directly.

You can see that it’s looking for this event in the FormInterceptor class, (in the turbo source).

Programmatically triggering a click on a button in the form is a good workaround to ensure the submit event is fired, however, you can simply use dispatchEvent to achieve the same thing:

this.formTarget.dispatchEvent(new CustomEvent('submit', { bubbles: true }))

I can confirm that this does work and does not require any hidden buttons :slight_smile: (might want to confirm browser compatibility though - my project only targets the latest browsers).


With regards to the autocomplete, wouldn’t it work to use a little bit of stimulus & a turbo-frame like this?

<div data-controller="autocomplete">
  <form method="get" action="search" data-turbo-frame="search-results" data-autocomplete-target="form">
    <input name="q" data-action="keyup->autocomplete#search">
  </form>
  <turbo-frame id="search-results">
    <div class="result">...</div>
    <div class="result">...</div>
  </turbo-frame>
</div>
// autocomplete_controller.js
export default extends Controller {
  static targets= ['form']

  search() {
    this.formTarget.dispatchEvent(new CustomEvent('submit', {bubbles: true}))
  }
}

I think you could also add in debouncing to reduce server strain. While it’s marvelous how simple this is from a client-side implementation perspective - I think autocompletes are fraught with edge-cases, what if one of the search queries arrives out of order and such… Not that those problems aren’t solvable, but they’re certainly ignored here.


I’m also trying to wrap my head around when it makes the most sense to use a turbo frame and turbo streams. You could clearly do this with a turbo stream as well. Would be curious to see if there’s clear advantages to that approach over this one!

9 Likes