Turbo Stream action for remove and [append/prepend/...]

Currently there are only 7 default actions for turbo-stream.

How about we get an extensions of other actions such as remove-and-append or remove-and-prepend etc.

Currently I am using jQuery to resolve this issue but if it can be resolved with turbo, it would be much better.

I am just a beginner. Don’t take my french seriously. Would love to know your thoughts on this.

Are you familiar with custom turbo stream actions?

2 Likes

I will give it a read.

Although I once tried to do it with jQuery and stimulus but it was a lot of gymnastics.

This is so great! Being able to create a custom visit Stream action is going to solve a lot of my problems, I think.

I just wanted to drop this here since being able to create a custom stream action helped me figure out how to handle a transcluded Form inside another page:

Coming from a ColdFusion background, most form POSTs are followed by a 302 redirect with a Location header. However, if I use a Location inside a <turbo-frame>, then I can only update the contents inside that frame, which can be problematic if I want to update anything outside that frame (as well).

I know that most people in Hotwire will use Streams to perform append and replace actions. But, as a baby-step, I wanted to use a custom visit action to tell the parent page to reload two different frames. This incurs more network latency, obviously; but, is a relatively straightforward mental model coming from ColdFusion.

It’s also valid to have multiple streams in the same response. For example, I use

 <turbo-stream action="append" target="pagedList">
	<template>
Content 
</template>
</turbo-stream>
<turbo-stream action="remove" target="LoadMoreButton">
	<template>
	</template>
</turbo-stream>

I find that this does the same, but requires less extending in the front end. I usually make a helper in my backend that takes multiple streams and creates a response.

1 Like

@krebil It is possible but that would reset the state of the removed item, for instance, an expandable list.

@tleish I have followed all the steps. JavaScript is loaded perfectly but still it can’t process the returned custom frame.

I even followed the video tutorial from here. But it is still not working on my end.

Here the issue that I get in the console when a turbo-frame is returned.

Typing Turbo.StreamActions even has the custom functions.

Here is the dump of my custom actions.

import {StreamActions} from "@hotwired/turbo";


console.log("Before")
console.log(StreamActions);

StreamActions.console_log = function () {
    console.log("CONSOLE LOGGING");
}

StreamActions.toast = function () {
    console.log("TOASTER");
}

console.log("After");
console.log(StreamActions);

I’m not sure i understand what states an expandable list would have that wouldn’t work with this approach. I would let my HTML hold the state by removing/adding the content when necessary.

<div id="expandable-list">
  <div>
    This is the content that will always be shown
  </div>
  <div id="expanded-list-content">
    this can be replaced when expanding/collapsing
  </div>
</div>

Then a steam to expand the list

<turbo-stream action="replace" target="expanded-list-content">
	<template>
          <div id="expanded-list-content">
              'All your expanded content'
              <a href="/collapse">collapse</a>
          </div>
	</template>
</turbo-stream>

And then to collapse

<turbo-stream action="replace" target="expanded-list-content">
	<template>
      <div id="expanded-list-content">
        'empty content'
        <a href="/expand">expand</a>
      </div>
	</template>
</turbo-stream>

If the amount of content is very small I would probably not bother using streams at all and just use styling to hide to the content when collapsing.

Side-note: I strongly prefer to have my logic in the backend and as a result i prefer to restructure my HTML so that I can use turbo without stimulus unless i specifically need something that enhances the user experience. You may not feel the same and that’s totally valid as well

Check if 1) the version of Turbo you are running >= 7.2.0, 2) StreamActions is defined (not Turbo.StreamActions.) or 3) if you have an error importing the module, like:

Uncaught TypeError: Failed to resolve module specifier “@hotwired/turbo”…

If StreamActions is undefined, use Turbo.StreamActions.

- import {StreamActions} from "@hotwired/turbo";


console.log("Before")
- console.log(StreamActions);
+ console.log(Turbo.StreamActions);

- StreamActions.console_log = function () {
+ Turbo.StreamActions.console_log = function () {
    console.log("CONSOLE LOGGING");
}

- StreamActions.toast = function () {
+ Turbo.StreamActions.toast = function () {
    console.log("TOASTER");
}

console.log("After");
- console.log(StreamActions);
+ console.log(Turbo.StreamActions);

or fix the import module, something like the following might resolve your issue, depending on how your using the module:

- import {StreamActions} from "@hotwired/turbo";
+ import { StreamActions } from 'https://cdn.skypack.dev/@hotwired/turbo';
1 Like

Sorry for the late response. It was fixed by using Turbo.StreamActions. Btw, why is there this confusion between Turbo.StreamActions and StreamActions