Trigger a frame update in javascript

Trying to work through a particular UX design, and here’s where I want:

  • User is shown a form with a lot of dropdowns (they are mapping a CSV file to DB columns in the app)
  • User changes a dropdown (the column mapping), which triggers a form post to rails
  • Rails gives back two turbo frames to replace the form (with validation info) and another frame (an example mapping of their data) that is generated as they change the dropdowns.

Current issue is that a form submit to rails, and sending down frames DOES work, but the history / url changes so that a refresh of the page would cause an error. (Doing a get on a post route) This is intentional from Turbo, and has to work this way I understand due to the browser and history.

After some experimenting and discussion on another thread here, I’m working with vanilla js fetch() to “submit” the form via AJAX, get the same frames from Rails, then replace those frames myself from the returned HTML turbo-stream commands.

Rather than parse out this string and do the dom manipulation - surely there are functions in Turbo to do this, since it does this already with frames? Is there any way I can invoke Turbo via JS to take the returned string and do its normal work to replace the frames found within the string?

OR, am I totally doing this wrong, and there is a better, unobtrusive way?

1 Like

You can use request js to make the request. It is a wrapper around the fetch api that handles alot of stuff for you like crsf tokens and also turbo-streams. It will automatically return turbo-streams if you set a turbo stream response but you can also specify it as the response kind that you want. Here is an example.

await post('localhost:3000/posts')

Now it should respond with your turbo stream responses and run them automatically
you can also specify turbo-stream as the response intended with responseKind option

await post('localhost:3000/posts', { responseKind: "turbo-stream" )

checkout the github repo for more info GitHub - rails/request.js

Great, thank you! I’ll check it out.

Yeah, this looks like the right solution, unfortunately it did everything except replace the turbo-frames - so either I’m doing it wrong, or there’s some issue with the script. I’ve posted the question to them on github if anyone cares to follow along.

And, the problem was my own - not turbo or request.js. Typo in my turbo-frame name. Thanks @yunggindigo for the great help!

1 Like

@DaveSanders out of interest have you been returning 4XX status codes to request.js for validation info?

The reason I ask is I have been using request.js to perform autosave functionality and render inline errors returned in a turbo stream response. This works great in the sense request.js submits the form and then displays the error messages by rendering the turbo stream response. However, if I return a 4XX status code, which i’d like to because there is a validation error, it doesn’t work because request.js’s perform function checks if the response is ok before rendering the turbo stream, and the response is not ok because it is not a 200 (source).

Would be interested to hear if your experiences.