Hacker News new | ask | show | jobs
by 023984398 1911 days ago
This is cool but its not using hotwire (turbo frames / turbo streams)
1 comments

It does! Stimulus 2 is Hotwire too[0].

Turbo seemed more connected with existing models, and so I chose a Stimulus controller instead. But maybe I just don't know Turbo as much yet.

[0] https://stimulus.hotwire.dev/

The whole idea of Hotwire is to prevent `Rails.ajax` calls. You can easily accomplish this with less code:

1. Replace the `output` target with a Turbo frame. 2. Add a value to the `data-controller` div with a `preview-url`: https://stimulus.hotwire.dev/reference/values 3. Change the `Rails.ajax` call with `let url = URL.new(this.previewUrlValue); url.searchParams.append('body', this.tweetTarget.value; this.outputTarget.src = url.toString();` 4. Change the `preview` action to render HTML with the same frame.

Now you have an automatic refreshing frame with less code.

There are a lot of ways to skin this cat!

You can also have a hidden form submission that does this from the existing controller so you don't need to specify the URL.

For example, you can add a hidden submit button like

  form.submit 'preview', data: { composer_target: 'submit' }, hidden: true
Instead of a stimulus target, you wrap your preview area in a turbo frame

  <turbo-frame id="output">
  ...
  </turbo-frame>
In your (ruby) controller you can re-use the existing controller action:

  def create
    @post = Post.new(post_attributes)
    preview && return if params[:commit] == 'preview'
    ...
  end
Do the turbo junk in a private method for the preview:

  private

  def preview
    render turbo_stream: turbo_stream.replace(
      'output', partial: "posts/preview", locals: { post: @post }
    end
  end

Your stimulus controller now just does this:

  preview() {
    this.submitTarget.click();
  }
I'm not sure which I prefer!
Yep, that's what actually cross my mind first. In the end, I wanted to avoid depending on the model, but it's certainly interesting.
Once the complexity ramps up and the side effects compound, that's when I really appreciate server side rendering. And incidentally, that's exactly when I like to have the whole model!

I just refactored some old jquery stuff to use turbo and stimulus on a really complex form and it turned out well, I think. But below a certain level of complexity, it would have made sense to just do everything directly in stimulus with no AJAX at all.

I know your preview example is contrived (it's tough getting a real-world representative demo into a blog post, so please don't read this as criticism, I don't mean to say it's a bad example and I'm not trying to pick on it!) but really simple use cases are exactly the "sweet spot" for doing everything directly in the browser using Stimulus without having to call back to the server. Only once you start piling in business logic or reshuffling major parts of the display around does it fully pay off, and that's also about when you'll start appreciating having the whole model and the ability to re-use partials (rather than having to pick off a few pieces manually).

EDIT:

And just to be clear, in the sample code I put in above, you don't actually have to use the model. You can always just shove a single parameter into a special partial and go.

Perfect. I will try it, and perhaps update the post with this approach as well. Thank you. I haven't done anything with Turbo yet, although it's my next step. I first just tried to refresh my Stimulus knowledge with the 2.x changes.

But as for the AJAX call, I still think it's quite simple solution that most will instantly understand (and that's a good thing).

> "I will try it, and perhaps update the post with this approach as well."

this would be very useful, as there are not many comparative articles that really help you choose one approach over another. a number of years ago, i went through a couple rounds of turbo vs. ujs vs. websockets vs. custom js vs. something other library i don't remember atm, to try to figure out the best option for the app i was working on. lots of articles talk about the strengths of a library compared to others, but almost none walk through an example (or two) with enough depth to show those differences explicitly.

I included a second example with Turbo Frame that hopefully shows how Turbo Frames work.
I mean technically they are installed but the example is still using UJS and not the functionality provided by the hotwire libs.
Yes, I was only focusing on Stimulus 2, but someone else posted here how to change the example to use a frame.
At least in the non-rails environment, Turbo and Stimulus are two separate libraries and have to be included individually.