Is this correct?. A Stimulus controller to use turbo_stream GET requests to avoid updating browser history

Hello there, hoping you’re having a good week/end.

So, i had an issue in that i had resources that would need to be accessed with .turbo_stream formats. But, i needed them not to update the browser url. The standard Turbo way(that i know of) is that you would place it within a frame, then it would update the frame’s url and not the browsers.

But, i had cases where the link was not inside a frame tag. It was a normal link ( <a> tag), i don’t want to rely on Rails-UJS to do that through supplying data-method attribute on the frame. In case it’s removed in the future(from our App).

For this reason, I created a simple Stimulus controller, that would use Request.js to send a GET request to the server(without updating the browser history)

import { Controller } from "@hotwired/stimulus"
import { get } from "@rails/request.js"

export default class extends Controller {
  requestTurboStream({ currentTarget }) {
    get(currentTarget.dataset.url, {
      responseKind: "turbo-stream",
    })
  }
}

Then, i would tranform the linkinto something like

<button data-controller="turbo-stream" data-url="url" data-action="turbo-stream#requestTurboStream">

</button>

Is this an accepted behaviour, or should i rely on Rails-UJS and keep using data-method on the anchor tags.

Thank you for your answers.

Bests

1 Like

This is pretty much exactly what I do, haven’t had a general need yet but I use this in a number of controllers that have a specific need to be handled like you suggest.

Works like a charm for me.

1 Like

You don’t need to place the link “within a frame”. You can place the frame anywhere on the page and put a data-turbo-frame on the <a> tag.

<a href="/messages/1" data-turbo-frame="messages">
  Following link will replace the the messages frame.
</a>

<turbo-frame id="messages"></turbo-frame>
1 Like

Yes, you are correct.

If i remember correctly, i think DHH said that frames are only to update a single part of the page, i.e their corresponding <turbo-frame> tag.

Is doing something like

<turbo-frame>
   <turbo-stream action="append" />
</turbo-frame>

A discouraged pattern?.

The understanding i have of Turbo Frames is that if i’m going to replace a single element on the page, i would use frames. If more than one, i use Turbo Streams. Am i wrong?.

Thanks for your reply.

Another way to put this is, turbo-frames CAN only update a single page of the page. turbo-streams CAN be used to update more than one part of the page.

I’m not familiar with any suggestions around this being a discouraged pattern. The documentation neither suggests, nor discourages combining them for GET requests.

<turbo-frame id="messages">
   <turbo-stream action="append" target="message_1" />
   <turbo-stream action="replace" target="page-title"/>
</turbo-frame>

Not necessarily.

turbo-frame turbo-stream turbo-stream inside a turbo-frame
Modify Single Element using NON-GET x x
Modify Single Element using GET x x
Modify Multiple Elements using NON-GET x x
Modify Multiple Elements using GET x
1 Like