Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure (Hiccup): How can I know which submit button got pressed in a form?

I have a form, using hiccup framework. It looks like this:

(form-to {:enctype "multipart/form-data"}
  [:post "/add-data"]

  ...

  (submit-button {:class "btn"} "Save")
  (submit-button {:class "btn} "Clone"))

How do I know which submit button got pressed, without using jQuery/javascript?

I looked at the Hiccup's documentation for request. But, the request element does not have a lot of documentation.

like image 267
sakh1979 Avatar asked Mar 18 '23 09:03

sakh1979


2 Answers

A complete example looks like:

(ns myapp.routes.home
  (:use [hiccup core form])
  (:require [compojure.core :refer :all]))

(defn quick-form [& [name message error]]   
  (html
   (form-to {:enctype "multipart/form-data"}
    [:post "/form-out"]
   (text-field "Hello")
   (submit-button {:class "btn" :name "submit"} "Save")
   (submit-button {:class "btn" :name "submit"} "Clone"))))

Note that using the same name for both submit buttons allows you to do a simple lookup of the "submit" key in the result map.

(defroutes home-routes
 (GET "/form-in" [] (quick-form))
 (POST "/form-out" [:as request] (str (request :multipart-params))))

When opening the following page:

 http://localhost:3000/form-in

And filling the form, the result out of the POST route is:

 {"submit" "Save", "Hello" "hello2"}

By the way, I found an old useful post about the way the request map is structured in Compojure, so it makes it easier to destructure it in the Clojure code.

like image 116
Nicolas Modrzyk Avatar answered Apr 06 '23 07:04

Nicolas Modrzyk


submit-button generate HTML <input type="text" ...> element. You can add "name" and "value" attributes to them:

(submit-button {:name "button" :value "save" :class "btn"} "Save")
(submit-button {:name "button" :value "clone" :class "btn"} "Clone")

and find it out in your server side code. In your case lib-noir is used. But recent version of lib-noir no longer provide utils for destructuring requests and encourage people to utilize other libraries like Compojure or bare Ring.

Basically you need: - ensure your server side app use wrap-params Ring middleware - in case the above "Save" button is click, your server side handler for [:post "/add-data"] should receive a hash map like this:

{:http-method :post
 :uri "/add-data"
 :form-params {"button" "save"
               ;; other form data as key/value pairs
               ;; where: key is input element's "name" attribute and value is input element's "value" attribute
               ...
               }
 ...}

I hope you can figure out yourself how to find the value you need in such a map.

More in-depth reading:

https://github.com/mmcgrana/ring/wiki/Parameters

like image 34
myguidingstar Avatar answered Apr 06 '23 08:04

myguidingstar