Skip to content

Instantly share code, notes, and snippets.

@rcampbell
Created December 29, 2009 14:59
Show Gist options
  • Save rcampbell/265355 to your computer and use it in GitHub Desktop.
Save rcampbell/265355 to your computer and use it in GitHub Desktop.
Dynamic form population for Enlive
;; Dynamic form population based on Christophe Grand's suggestions found here:
;; http://bit.ly/72NkNS
(ns dynamic-form
(:refer-clojure :exclude [empty complement])
(:use net.cgrand.enlive-html)
(:import [java.io File]))
(defn populate-select [options]
(fn [node]
(at node [:option]
(clone-for [option options]
(do-> (set-attr :value (option :value))
#(if (option :selected)
((set-attr :selected "selected") %) %)
(content (option :name)))))))
(defn populate-input [value]
(fn [node]
(let [type (keyword ((node :attrs) :type))]
(cond (or (= :text type)
(= :hidden type)) ((set-attr :value value) node)
(or (= :radio type)
(= :checkbox type))
(#(if value ((set-attr :checked "checked") %) %) node)))))
(defn populate-field [value]
(fn [node]
(let [tag (node :tag)]
(cond (= :select tag) ((populate-select value) node)
(= :textarea tag) ((content value) node)
(= :input tag) ((populate-input value) node)
:else node))))
(def dynamically-populate
#^{:doc "Iterates over a map, selecting the template's form
fields whose ids match the keys and populating them
with the corresponding values"}
(let [source (html-resource (File. "./template.html"))]
(fn [m]
(reduce
(fn [source [k v]]
(transform source
[(selector [(id= (name k))]) (populate-field v)]))
source m))))
;; Result of transformation on "template.html"
(dynamically-populate
{:size
[{:name "16x16", :value "size_code_1"}
{:name "20x20", :value "size_code_2", :selected true}],
:engraving "Rob C",
:wrapped true,
:customization "none, thank you"})
({:tag :html,
:attrs nil,
:content
["\n"
{:tag :head,
:attrs nil,
:content
["\n\t"
{:tag :title,
:attrs nil,
:content ["Enlive's Dynamic Form Population"]}
"\n"]}
"\n"
{:tag :body,
:attrs nil,
:content
["\n\t"
{:tag :form,
:attrs {:id "coordinates"},
:content
["\n\t\t"
{:tag :input,
:attrs {:value "Rob C", :type "text", :id "engraving"},
:content []}
"\n\t\t"
{:tag :input,
:attrs {:checked "checked", :type "checkbox", :id "wrapped"},
:content []}
"\n\t\t"
{:tag :select,
:attrs {:name "size", :id "size"},
:content
["\n\t\t\t"
{:tag :option,
:attrs {:value "size_code_1"},
:content ("16x16")}
{:tag :option,
:attrs {:selected "selected", :value "size_code_2"},
:content ("20x20")}
"\n\t\t"]}
"\n\t\t"
{:tag :textarea, :attrs {:id "customizations"}, :content []}
"\t\n\t"]}
"\n"]}
"\n"]})
<html>
<head>
<title>Enlive's Dynamic Form Population</title>
</head>
<body>
<form id="coordinates">
<input id="engraving" type="text" />
<input id="wrapped" type="checkbox" />
<select id="size" name="size">
<option value=""></option>
</select>
<textarea id="customizations"></textarea>
</form>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment