Firing a Turbo Stream from Stimulus

I have this form:

What I hoped to achieve here, is by clicking on this button, to fire a controller action
that will using turbo stream, replace this form with extra fields.

I made the request using fetch:

cep_search(event) {
event.preventDefault()
const token = document.getElementsByName(
  "csrf-token"
)[0].content;
let formData = new FormData()
formData.append("tipo_unidade", "fisica");
formData.append("cep", this.cepTarget.value);
formData.append("authenticity_token", token);
fetch(this.urlValue, {
  body: new URLSearchParams({
    'tipo_unidade': 'fisica',
    'cep': this.cepTarget.value,
    'authenticity_token': token
  }),
  method: 'POST',
  credentials: "include",
  headers: {
    "X-CSRF-Token": token,
    "Accept": 'text/vnd.turbo-stream.html, text/html, application/xhtml+xml'
  },
})

}

And it fires the controller:

Processing by UnidadesController#render_form as TURBO_STREAM

Parameters: {“tipo_unidade”=>“fisica”, “cep”=>“01548030”, “authenticity_token”=>"[FILTERED]", “empresa_id”=>“takitani”}
User Load (0.7ms) SELECT “users”.* FROM “users” WHERE “users”.“id” = $1 ORDER BY “users”.“id” ASC LIMIT $2 [[“id”, 2], [“LIMIT”, 1]]
Empresa Load (0.7ms) SELECT “empresas”.* FROM “empresas” WHERE “empresas”.“slug” = $1 LIMIT $2 [[“slug”, “takitani”], [“LIMIT”, 1]]
↳ app/controllers/unidades_controller.rb:21:in `load_empresa’
Rendered unidades/_fisica.html.erb (Duration: 7.2ms | Allocations: 6099)

But it renders nothing, the response comes empty.

If I do it by using a form, it works fine.

What am I missing?

Thanks!

1 Like

This doesn’t answer your question, but hopefully it will help identify/solve your problem: are you able to give a little more context on what you are trying to do and why? (besides what has been said about adding form fields upon clicking the submit button)?

Sure! Thank you so much for taking the time to answer.

This is a address form.

When you fill in the zip code, and click the seach button, it should post to a controller action
and, using a Turbo Stream, replace the form with the street, state and city filled in.

I got it working by changing the form action and posting it, but it feels so wrong…

Normaly I would do this using ajax, but I’m trying to find a way to make it “right” using Turbo and Stimulus.

If you are using Rails, then why are you submitting the form via javascript? The form should probably be submitted with html - unless you have cogent reasons for doing otherwise. here are some proposed workflows - there might probably be better ways of doing this - i am myself getting familiar with these types of workflows, so perhaps take the following with a grain of salt

(A) with turbo stream to append/replace dom elements

  1. User types in the post code / zip code.

  2. This form is submitted via html

  3. A new form is created with the street/state/city filled in. This new form could replace the the old one. Build this new form with the turbo_stream.erb returned from the server.

       # zip_forms_controller
       def new
       end
    
      def create
           # turbo stream response replacing the form with another form with the city/address details
           # the new form could point to another controller: city_form_controller with an associated create action.
      end
    

(B) Simply using turbo frames

Same concept:

1& 2. as above
3. a new form is presented with all the addresses etc. filled out.

# zip_code_forms/new.html.erb
<%= turbo_frame_tag "new_address" do %>
     etc.
<% end  %>

# zip_code_controller.rb
def create
  if zip_code_found
     redirct_to new_city_form(params[:city])
  else
  end
end

# city_forms/new.html.erb
<%= turbo_frame_tag "new_address" do %>
     populate the city and state information here
<% end  %>
2 Likes

Thanks for your response.

I’ve ended up using a stimulus controller to post the form to a different action that renders the form again.

Because the form is either posting to create or patchin to update, I’ve prefered to post to a different action than dealing with that on both actions.

1 Like