How to auto-reload frame?

I’m playing around with Turbo frames using Rails. A TurboFrame can be lazy-loaded by using the src attribute. This is great, but what about auto-reloading a frame every few seconds?

I want to display a time series chart which needs to update itself. There is no server side event for doing a TurboStream broadcast. A simple polling mechanism is required. How can the frame reload itself?

1 Like

Could this topic be of use?

Thanks, it seems that Turbo.visit() can load a frame, too. But it changes the URL in the address bar (pushes to history), so it does not help me yet. I’m looking for a way to fetch a frame and do the div replacement - nothing more.

Currently I’m trying to understand the Turbo sources…

Ah, I see that the previous discussions have mostly been focused on forms.

What about setting the frame src to (the same) URL in your code? I’ve tried manually setting the src for a turbo-frame element repeatedly and it does make Turbo fetch a new version each time.

1 Like

Thanks a lot, @stgm, setting the src attribute to trigger a reload works fine!

Now I’ve made this Stimulus.js controller:

// app/javascript/controllers/refresh_controller.js
import { Controller } from "stimulus"

export default class extends Controller {
  static values = {
    src: String
  }

  connect() {
    this.timeout = setTimeout(() => {
      this.element.setAttribute('src', this.srcValue)
    }, 5000);
  }

  disconnect() {
    clearTimeout(this.timeout)
  }
}

Usage in a Rails partial:

<%= turbo_frame_tag 'stats', 
      data: { controller: 'refresh', refresh_src_value: request.path } do %>
  <p>Updated content</p>
<% end %>
3 Likes

This is cool, thanks for that. However, I couldn’t get it to continually poll, it just refreshes the turbo-frame once.

I want to poll a turbo-frame continually until a background job is finished, and then show the result (and stop polling). I don’t see how to make this work with turbo-frames, as it only replaces the contents, but does not update the attributes of the turbo-frame.

Is something like that possible with turbo-frames?

There’s a reload method on a frame now - just call that if you want to refetch the contents.

Previous to this you could achieve a reload by changing the src attribute and changing it back, which is exactly that the reload method does :slight_smile:

  reload() {
    const {src: src} = this;
    this.src = null;
    this.src = src;
  }