Noob question - Dynamically create URL based on submission of text in form_for?

I’m trying create a form that let’s the user input the last portion of the URL to be routed to. Here’s the line from my router:
get “/memberships/courseId/:courseId”, MembershipController, :show
That works fine when I type a URL in the address field of my browser, like https://localhost:4000/memberships/courseId/1.

But, I want the user to be able to submit a form, containing the “1” and get to the same place.

I’ve not been able to do that to date. Instead I have this as the form:
<%= form_for @conn, membership_path(@conn, :select ), [as: :session, method: :get], fn f2 -> %>
<%= text_input f2, :newCourseId %>
<%= submit “Submit” %>
<%end %>

You submit the above form and that gets routed to the select method of the controller. Select pulls the newCourseId and then forwards to the URL where we want to be:

def select(conn, %{“session” => session}) do
newCourseId = session[“newCourseId”]
redirect conn, to: membership_path(conn, :show, newCourseId )

The above sends the browser to memberships/courseId/{newCourseId} which then is routed. For example if you put a 1 in the text field of the form and submitted it you would get redirected to memberships/courseId/1 by the router:
get “/memberships/courseId/:courseId”, MembershipController, :show
Then you are sent to the show method of the controller.

That’s a roundabout way! Is there a way to get directly there from the form submission?

Full project is here:


There are a couple of ways I could see doing this without the redirect. Personally, I’d just use Javascript to get it done. Have a link that gets updated with whatever value is in the text field. The only other way I could see this working is if you had the endpoint you’re posting to render the template, but that would require having the content exist at two different URLs.

1 Like

If you want that to be without any kind of redirect (either at the router level or controller level) you need to use either javascript or something like drab for elixir since you need to do it at runtime on the client end.
With javascript (or jQuery, or a dynamic component from Vuejs) you can instead of having a submit button have a link (with the style of a button if you will) where the href gets updated to reflect the input the user types.

With jquery (for the sake of simplicity) given a:

<%= text_input f2, :newCourseId %>
<a href="" id="my_dynamic_link" class="button-style">Submit</a>

Then on the js:

$("#id-of-text-input").on('change', function() {
  $("#my_dynamic_link").attr("href", "https://localhost:4000/memberships/courseId/" + $(this).val());

(not sure the ‘change’ listener is enough, perhaps ‘keyDown’ & ‘keyUp’ together work better)

With VueJS you would do a binding between changes on the input and the href as well (but it’s a significant overhead using VueJS or any other lib just for this)
You will need to account for things like production & development domains, etc.

You could also bind the form submit action, and preventDefault() on the submit event, assembling dynamically the url and just doing a window redirect/location change.

If you want to do it on the server side you will still need to hook up a logical point to decide these redirects, this blog post shows an interesting approach:

You would instead of re-assembling the path+query_string , build a single path from the query string.

Still the most straightforward way is using JS, and it doesn’t execute a technical redirect on the server side.

1 Like