Hotwire Discussion

How to prevent turbo:submit-end from following redirect?

Hi,

I found a few similar topics, but unfortunately no solution at all. Hopefully somebody can help me out.

So I expect, what I want to do is not how drive is designed, but please give me a hint, how to accomplish my situation.

I have a stimulus popup controller (based on Super easy modals with Rails and Stimulus (and a bit of Tailwind)), which loads different kinds of views all over the application.

Each of those loaded views, may be loaded in this popup, but also as the main view of the application, or they may be load in a turbo-frame. It simply depends on the context, in which the user wants to interact with some information.

However, in the most cases, when we open a popup, there’s a form in it, which provides the user the possibility of modifying some data.

Turbo handles the form-submission fine, if there are errors (status code 422), then the form is just replaced in the modal including the error messages. Just like designed.

But if the request was successful, a redirection occurs.

Sure, that’s because the controllers’ default is to respond with the redirection in the response, if the update was successful. This is also a good behaviour for all other contexts, in which those views may be rendered.

But in the case of the modal, the expected behaviour would be, that the model just closes (and raises an event to some subscribers, that it updated some data successfully). But it should NOT redirect the whole page.

I also don’t think, it would be a good solution to send some more http headers from within the popup, and modify each controller, to prevent the redirection for this special “request-from-popup-case”.
I also don’t like the idea of wrapping all of those views in separate turbo-frames, as this might also have side-effects in some other contexts.

Actually I’d expect I should be able to subscribe to the turbo:submit-end event (what’s actually possible).
This is pretty good, as I can read the information, if the submission was successful or not.
Now I can inform several subscribers with a CustomEvent, that the change in the modal was done properly.

But in the end a full redirection appears.

I thought I simply could call event.preventDefault(), but unfortunately it doesn’t prevent turbo from performing the redirection.

What am I missing?

Thanks alot for your help!

Hi!

First of all, always adding a reduced conde example of what you’re trying to do is even better so we can understand it more and even run it locally.

My first instinct is if you have a modal with a form that will update n places in the current view after success submission will be to use turbo streams. Form submissions goes with the header text/vnd.turbo-stream.html (more info here) that rails will understand as the format turbo_stream and you can do something like:

respond_to do |format|
  format.turbo_stream { render turbo_stream: ...}
  format.html { redirect_to messages_url }
end

So in this way you can avoid redirection when turbo is present.

Other option is to use turbo frames. If you wrap your modal in a frame the navigation will happen inside and then on success you can clear the form but this is not the best option I think.

This is my best response with the information that I have but if you want to provide a detailed example we can review it!

Cheers

Hi @faqndo97,

sorry for my delay and a possible information leak. I was assuming a basic rails setup.

So I now hope to deliver enough details… I just created a new rails project with rails version 6.1.4.1 just to be sure, I dont talk about obsolete things.

So when I scaffold a resource (lets do it with “blogs”), the generated controller for the update action deals with the formats/responses like this:

    respond_to do |format|
      if @blog.update(blog_params)
        format.html { redirect_to @blog, notice: "Blog was successfully updated." }
        format.json { render :show, status: :ok, location: @blog }
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @blog.errors, status: :unprocessable_entity }
      end
    end

And in my popup_controller.js

I attach to the turbo drive event “turbo:submit-end” with the goal to get the information if the submission was possible or not (in evt.detail.success)

In both cases I don’t want turbo to redirect the whole page (its in a turbo-frame).

If the request was not successful, turbo drive replaces the form on its own.
But if it was successful, I just want to raise my own event and keep the current page (the observers might have some ideas about what to do next).

But I am not able to prevent the redirection :frowning: - thats my problem

I pushed a simple demo app, to reproduce that behaviour. (
GitHub - pgruener/stimulus_popup_req: Stimulus Popup request to prevent close after form submission)

Just create a blog post with more than 4 characters in title . Afterwards open the modal in the “Edit” Modal.

If you try to change the title to 1-4 chars-length, the popup will be kept open, as errors appeared.

If you perform a valid change (title > 4 chars-length), you’ll directly hit a redirect from turbo. No matter if I preventDefault() or stopPropagation().

But something like that would be very useful for our scenario

Hope the issue more clear now, otherwise I’ll of course explain more if needed.

Thanks for your help

Cheers