# Form submit with turbo-streams response, without redirect

**URL:** <https://discuss.hotwired.dev/t/form-submit-with-turbo-streams-response-without-redirect/3290>\
**Category:** General\
**Created:** [September 27, 2021, 6:17pm UTC](https://discuss.hotwired.dev/t/form-submit-with-turbo-streams-response-without-redirect/3290 "2021-09-27T18:17:47Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![DaveSanders](https://yyz1.discourse-cdn.com/flex027/user_avatar/discuss.hotwired.dev/davesanders/32/1410_2.png) [@DaveSanders](https://discuss.hotwired.dev/u/DaveSanders)\
**Post date:** [September 27, 2021, 6:17pm UTC](https://discuss.hotwired.dev/t/form-submit-with-turbo-streams-response-without-redirect/3290/1 "2021-09-27T18:17:47Z")

</div>

Even though I’ve done turbo with forms and thought I understood the limitations, I’m having trouble getting this to work the way I want.

I have a page with two turbo frames, “mapping” and “example”. Mapping contains a form which is a list of select dropdowns. Stimulus is used to have each select’s “change” event submit the form.

Form submits fine, and then my controller returns two turbo stream frames to replace the “mapping” and “example” frames. This renders fine, but what I’m seeing on the browser is that the submit is getting a redirect from the server, and then just renders the text of my turbo-streams, rather than replace the contents in the page. (Presumably because of the redirect.)

How do I stop turbo from redirecting after the form submit, and instead replace the frames on the page?

Here are the controller actions involved:

```auto
    def mapping
      @mapping_fields = mapping_fields
    end

    def save_mapping
      @mapping_fields = mapping_fields
      streams = [
        turbo_stream.replace('mapping', partial: 'mapping'),
        turbo_stream.replace('example', partial: 'example')
      ]
      render turbo_stream: streams
    end

```

Here is the partial with my form:

```auto
<div turbo-frame='mapping'>
  <div data-controller='mapping'>
    <%= form_with url: :app_imports_save_mapping, data: { mapping_target: 'form' } do |form| %>
    <table>
      <% @import.headers.each_with_index do |header, i| %>
      <tr>
        <td><%= header%></td>
        <td>
          <%= form.select "mapping_#{i}", @mapping_fields, { include_blank: true }, data: { action: 'mapping#submit' } %>
        </td>
      </tr>
      <% end %>
    </table>
    <%= form.submit 'Next' %>
    <% end %>
  </div>
</div>

```

And stimulus is just doing a form.submit.

Thanks!

---

<div class="post-metadata">

**Author:** ![dan](https://yyz1.discourse-cdn.com/flex027/user_avatar/discuss.hotwired.dev/dan/32/1529_2.png) [@dan](https://discuss.hotwired.dev/u/dan)\
**Post date:** [September 27, 2021, 7:13pm UTC](https://discuss.hotwired.dev/t/form-submit-with-turbo-streams-response-without-redirect/3290/2 "2021-09-27T19:13:32Z")

</div>

> [@DaveSanders](#):
>
> And stimulus is just doing a form.submit.

Should be `form.requestSubmit`. If you do `form.submit`, Turbo can’t intercept the submission and can’t understand the turbo-stream response from Rails.

Note that you’ll need a [polyfill](https://github.com/javan/form-request-submit-polyfill) — [Safari doesn’t support `requestSubmit`](https://caniuse.com/?search=requestsubmit).

---

<div class="post-metadata">

**Author:** ![DaveSanders](https://yyz1.discourse-cdn.com/flex027/user_avatar/discuss.hotwired.dev/davesanders/32/1410_2.png) [@DaveSanders](https://discuss.hotwired.dev/u/DaveSanders)\
**Post date:** [September 27, 2021, 7:28pm UTC](https://discuss.hotwired.dev/t/form-submit-with-turbo-streams-response-without-redirect/3290/3 "2021-09-27T19:28:37Z")

</div>

> [@dan](#):
>
> form.requestSubmit

Perfect, thank you! That worked exactly how I needed it as far as I can tell

---

<div class="post-metadata">

**Author:** ![DaveSanders](https://yyz1.discourse-cdn.com/flex027/user_avatar/discuss.hotwired.dev/davesanders/32/1410_2.png) [@DaveSanders](https://discuss.hotwired.dev/u/DaveSanders)\
**Post date:** [September 27, 2021, 7:53pm UTC](https://discuss.hotwired.dev/t/form-submit-with-turbo-streams-response-without-redirect/3290/4 "2021-09-27T19:53:29Z")

</div>

Also, it looks like you can use:

```auto
Turbo.navigator.submitForm(this.formTarget)

```

and don’t need a polyfill in safari.

---

<div class="post-metadata">

**Author:** ![DaveSanders](https://yyz1.discourse-cdn.com/flex027/user_avatar/discuss.hotwired.dev/davesanders/32/1410_2.png) [@DaveSanders](https://discuss.hotwired.dev/u/DaveSanders)\
**Post date:** [September 27, 2021, 8:14pm UTC](https://discuss.hotwired.dev/t/form-submit-with-turbo-streams-response-without-redirect/3290/5 "2021-09-27T20:14:49Z")

</div>

However, I just realized that when I’m submitting the form like this, even though I’m returning Turbo stream replace blocks, Turbo is not updating the frames on the page with the updated data. I added some validation messages and while I can see them in the response, Turbo isn’t updating the page to match.

---

<div class="post-metadata">

**Author:** ![DaveSanders](https://yyz1.discourse-cdn.com/flex027/user_avatar/discuss.hotwired.dev/davesanders/32/1410_2.png) [@DaveSanders](https://discuss.hotwired.dev/u/DaveSanders)\
**Post date:** [September 27, 2021, 8:41pm UTC](https://discuss.hotwired.dev/t/form-submit-with-turbo-streams-response-without-redirect/3290/6 "2021-09-27T20:41:26Z")

</div>

Well, I’ve almost figured this out.

If I have Turbo.navigator.submitForm(this.formTarget) in my stimulus controller  
And, I have my form action in my rails controller render the full template (which includes my two turbo frames) WITH

```auto
render :mapping, status: :accepted

```

Then the form saves, the new HTML comes down from the server, the two turbo frames get updated and everything looks great.

EXCEPT, when I do this, the url changes in the browser to the url of the form, which then causes an error if the user refreshes because there is no “get” on the form save action route.

This is feeling very “whack-a-mole” to me, and at this point I could have been done with it using traditional AJAX - but I’m trying to move to the new Rails Way.

---

<div class="post-metadata">

**Author:** ![dan](https://yyz1.discourse-cdn.com/flex027/user_avatar/discuss.hotwired.dev/dan/32/1529_2.png) [@dan](https://discuss.hotwired.dev/u/dan)\
**Post date:** [September 27, 2021, 11:26pm UTC](https://discuss.hotwired.dev/t/form-submit-with-turbo-streams-response-without-redirect/3290/7 "2021-09-27T23:26:11Z")

</div>

What you’re running into is exactly [why Turbo requires a redirect for form submissions](https://github.com/hotwired/turbo/issues/22#issuecomment-750336078).

What was wrong with `render turbo_stream: streams`, as you’d originally intended?

---

<div class="post-metadata">

**Author:** ![DaveSanders](https://yyz1.discourse-cdn.com/flex027/user_avatar/discuss.hotwired.dev/davesanders/32/1410_2.png) [@DaveSanders](https://discuss.hotwired.dev/u/DaveSanders)\
**Post date:** [September 28, 2021, 3:05pm UTC](https://discuss.hotwired.dev/t/form-submit-with-turbo-streams-response-without-redirect/3290/8 "2021-09-28T15:05:27Z")

</div>

When using the streams, turbo doesn’t update the frames, even though I’m sending them down and see them in my network tab.

This is when using either this.formTarget.requestSubmit or Turbo.navigator.submitForm(this.formTarget)

I’m thinking at this point I don’t have a good way to get the UX I want unless I just do AJAX calls and manage the response client side. Which is fine, I’m sure this is an edge case and not Turbo’s fault. I was hoping though that there was a way to make it work without additional JS.

---

<div class="post-metadata">

**Author:** ![ParamagicDev](https://yyz1.discourse-cdn.com/flex027/user_avatar/discuss.hotwired.dev/paramagicdev/32/1933_2.png) [@ParamagicDev](https://discuss.hotwired.dev/u/ParamagicDev)\
**Post date:** [October 2, 2021, 12:42am UTC](https://discuss.hotwired.dev/t/form-submit-with-turbo-streams-response-without-redirect/3290/9 "2021-10-02T00:42:38Z")

</div>

Hey Dave 👋 if you are looking for standard AJAX behavior with a UJS like interface while still being able to use Turbo / Turbo Streams, I could point you in the direction of Mrujs. (A library I created intended to be a drop-in replacement for rails-ujs)

[https://Mrujs.com](https://Mrujs.com)

If you have any questions, feel free to stop by the StimulusReflex discord and I’d be happy to help in anyway I can.

> **[Join the stimulus\_reflex Discord Server!](https://discord.com/invite/stimulus-reflex)**
>
> Check out the stimulus\_reflex community on Discord - hang out with 1,525 other members and enjoy free voice and text chat.

---

<div class="post-metadata">

**Author:** ![lakim](https://yyz1.discourse-cdn.com/flex027/user_avatar/discuss.hotwired.dev/lakim/32/3451_2.png) [@lakim](https://discuss.hotwired.dev/u/lakim)\
**Post date:** [September 27, 2023, 8:05am UTC](https://discuss.hotwired.dev/t/form-submit-with-turbo-streams-response-without-redirect/3290/10 "2023-09-27T08:05:01Z")

</div>

Have a look a this post for a nice solution to this problem using [request.js](https://github.com/rails/request.js):

> [@Triggering Turbo Frame with JS](https://discuss.hotwired.dev/t/triggering-turbo-frame-with-js/1622/54):
>
> The requestSubmit method did not work in my case, I think because the search form was already nested in higher level form (autocomplete field in a form). What I like to do now for simple actions that trigger a Turbo Stream is to use [request.js](https://github.com/rails/request.js) to send the HTTP request. It has a [responseKind option](https://github.com/rails/request.js#responsekind) that you can set to turbo-stream. It will set the Accept Header to text/vnd.turbo-stream.html so the backend will respond with a Turbo Stream. I think this trick deserves to be better known from Hot…

---

<div class="post-metadata">

**Author:** ![jbonnier](https://yyz1.discourse-cdn.com/flex027/user_avatar/discuss.hotwired.dev/jbonnier/32/3571_2.png) [@jbonnier](https://discuss.hotwired.dev/u/jbonnier)\
**Post date:** [January 20, 2024, 5:55am UTC](https://discuss.hotwired.dev/t/form-submit-with-turbo-streams-response-without-redirect/3290/11 "2024-01-20T05:55:45Z")

</div>

Is there any documentation for that method?

---

<div class="post-metadata">

**Author:** ![woto](https://yyz1.discourse-cdn.com/flex027/user_avatar/discuss.hotwired.dev/woto/32/759_2.png) [@woto](https://discuss.hotwired.dev/u/woto)\
**Post date:** [March 23, 2024, 2:44pm UTC](https://discuss.hotwired.dev/t/form-submit-with-turbo-streams-response-without-redirect/3290/12 "2024-03-23T14:44:47Z")

</div>

I also asked myself this question. But nevertheless it works great, as it should.
