Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The documentation does not mention that Stream Action tags can be rendered inside any HTML #1258

Open
radanskoric opened this issue May 13, 2024 · 5 comments · May be fixed by hotwired/turbo-site#192 or #1263

Comments

@radanskoric
Copy link
Contributor

The way Turbo is currently implemented, stream tags will be processed and executed when they are rendered anywhere in HTML.

Here is a minimal example with a static HTML page:

<html>
  <head>
    <script src="https://unpkg.com/@hotwired/turbo"></script>
  </head>
  <body>
    <turbo-stream action="append" target="list">
      <template>
        <li>list element</li>
      </template>
    </turbo-stream>

    This list has an element added via the stream action:
    <ul id="list">
    </ul>
  </body>
</html>

This will work anywhere where stream tags are rendered into the page DOM:

  • Anywhere inside the initial page HTML.
  • As part of the turbo frame response as long as it is rendered inside the frame tag. Since content from outside the frame is not rendered into the actual document, the tag needs to be inside the frame for this to work.
  • If any javascript at any point rendered a turbo stream element anywhere inside the document DOM.
  • If a stream action renders HTML content (like it does in the example above) and that content in turn also has a stream action tag inside it, the second action tag will also work.

Not all of those are smart ways to use it but I was surprised that the documentation makes no mention of the feature. At least I couldn't find any mention anywhere in the documentation or old release notes.

I am guessing that the reason is that this is a side-effect of how StreamElements are implemented: They are defined as customElements with the stream tag execution being triggered by the connectedCallback implementation of the StreamElement class.

Perhaps it's just me and most other people find this clear without being mentioned but I think it would still be worth adding a few sentences and a documentation and a test to cover it. This can be a very useful feature in some cases.

I'd be very happy to mention this in the documentation but wanted to first check if there is something I am missing?

Can someone confirm that this is an intentional Turbo feature that should be mentioned explicitly in the documentation? If not, can we make it an official feature. Considering how it's implemented, one would have to do add explicit hacks just to stop it from working.

@seanpdoyle
Copy link
Contributor

Can someone confirm that this is an intentional Turbo feature that should be mentioned explicitly in the documentation?

I've personally relied on the behavior that you've described. For example, you can nest a <turbo-stream> element inside a <template> element, then append that content to the page after a <button> click (try it out on JSFiddle):

<script>
  addEventListener("click", ({ target }) => {
    const button = target.closest("button")
    const template = button.querySelector("template")
    document.body.append(template.content.cloneNode(true))
  })
</script>

<button type="button" id="call-to-action">
  <span>Click me to insert the template's contents after this button!</span>

  <template>
    <turbo-stream action="after" target="call-to-action">
      <template><p>You clicked the button!</p></template>
    </turbo-stream>
  </template>
</button>

@radanskoric
Copy link
Contributor Author

I've personally relied on the behavior that you've described. For example, you can nest a <turbo-stream> element inside a <template> element, then append that content to the page after a <button> click (try it out on JSFiddle):

Glad to hear that. :) I've used, in production, stream tags inside frame response (for extra side-effects) and inside the initial page load HTML (for interacting with some legacy JS).

@seanpdoyle
Copy link
Contributor

Can someone confirm that this is an intentional Turbo feature that should be mentioned explicitly in the documentation? If not, can we make it an official feature.

I think outlining these possibilities at a high level in the Streams Handbook section and in greater detail in Streams Reference section would be a big improvement!

@radanskoric
Copy link
Contributor Author

Can someone confirm that this is an intentional Turbo feature that should be mentioned explicitly in the documentation? If not, can we make it an official feature.

I think outlining these possibilities at a high level in the Streams Handbook section and in greater detail in Streams Reference section would be a big improvement!

Great, I'll prepare something soon. 👍

@radanskoric
Copy link
Contributor Author

@seanpdoyle I've opened two PRs to address this.

One to extend the documentation: hotwired/turbo-site#192

And one to add a test ensuring no regressions of this functionality: #1263

Happy to iterate on both based on feedback. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
2 participants