Chapter 5. Handling Form Input

In the previous chapter, we created a route handler to serve a sign up form. We also created the Selmer HTML template for this form, and as of now, it renders and looks pretty when we hit http://localhost:3000/signup. In this chapter, we're going to take it a bit further by:

  • Creating an endpoint to which the form will POST
  • Validating the form input
  • Reporting any form validation errors back to the user
  • Rendering a success template upon successful signup

Handling the form POST

There are typically three things we need to do when handling form input: validate the input, show an error message if the input is invalid, and show a success message when the input is valid and accepted.

In order for us to validate the form input, we need to create a route where the form will POST. We made a number of these in the previous chapter, so we'll draw on that experience and pattern.

Let's create a new route for the same URL, /signup, but this time we'll ensure that it accepts a POST request instead of a GET request. We'll put it along with the existing /signup GET route in our hipstr.routes.home namespace:

(defroutes home-routes
  (GET   "/"        []       (home-page))
  (GET   "/about"   []       (about-page))
  (GET   "/signup"  []       (signup-page))
  (POST  "/signup"  [& form] (str "nice job"))

We now have two routes for the same URL, one that will handle the GET request, and another that will handle the POST request. You'll notice that GET doesn't care about any parameters, however, POST uses Compojure's get the rest of the request map parameters destructuring syntax. This is just a bit of semantic sugar so that it's clear that we're working with just the values posted from the form instead of the entire request map.

That being said, the POST route doesn't do a whole lot for us at this point other than giving us a slightly sarcastic "nice job". Let's create a function similar to the existing hipstr.routes.home/signup-page function to handle the POST /signup response.

First, we need to make use of the ring.util.response namespace, as it has a function to issue a response redirect, which we can use to redirect the user to a sign up success page. Add the following to the hipster.routes.home namespace's :require key:

[ring.util.response :as response]

Next, we'll write the function to determine the appropriate response:

(defn signup-page-submit [user]
  #_(let [errors (signup/validate-signup user)]
    (if (empty? errors)
      (response/redirect "/signup-success")
      (layout/render "signup.html" (assoc user :errors errors)))))

In the preceding function, we validate the form using the hipstr.signup namespace (which we'll create next) and then, if successful, redirect the user to a sign up success page; otherwise, we repopulate the form and display the validation errors.

Note

For now we've commented out the let form, so that we can compile and refresh our pages as often as we like until the signup namespace is implemented.

Before we create the hipstr.signup namespace, let's quickly change our route handler to make use of the signup-page-submit function and add a route for the success page:

(defroutes home-routes
  (GET   "/"        []       (home-page))
  (GET   "/about"   []       (about-page))
  (GET   "/signup"  []       (signup-page))
  (POST  "/signup"  [& form] (signup-page-submit form))
  (GET "/signup-success" [] "Success!"))
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.188.57.172