add possibility to render forms with a single function

integration-tests
Josha von Gizycki 6 years ago
parent 31b18dec40
commit d0425d1a2c

@ -9,7 +9,7 @@
(defn new! [req]
(let [schema-uuid (get-in req [:params :schema])]
(if (form/valid? view-schema/new-attr-form req)
(if (form/valid? view-schema/attr-form req)
(do
(domain/create-new!
(get-in req [:params :name])

@ -1,18 +1,22 @@
(ns wanijo.framework.form
(:require [clojure.spec.alpha :as spec]
[hiccup.form :as hform]
[wanijo.framework.view :as view]))
[wanijo.framework.view :as view]
[ring.util.anti-forgery :refer [anti-forgery-field]]))
(spec/def ::label string?)
(spec/def ::required boolean?)
(spec/def ::spec keyword?)
(spec/def ::options
(spec/coll-of (spec/tuple string? string?)))
(spec/def ::widget
#(some (partial = %) [:input :select :checkbox :textarea]))
(spec/def ::field
(spec/keys :req-un [::label
::required
::spec]
:opt-un [::options]))
:opt-un [::options
::widget]))
(spec/def ::fields
(spec/and map?
(fn [map]
@ -34,8 +38,10 @@
(:clojure.spec.alpha/problems
(spec/explain-data spec-key field-value)))))
(defn field-valid? [value spec-key req]
(or (empty? (:form-params req))
(defn field-valid?[value spec-key req]
(or (or (and (contains? req :form-params)
(empty? (:form-params req)))
(empty? req))
(spec/valid? spec-key value)))
(defn field
@ -102,3 +108,69 @@
result))
true
(:params req)))
(defn render-input [id {:keys [label required spec]} values]
(let [value (id values)]
(list (when-not (field-valid? value spec values)
(spec-to-errmsg label spec value))
(hform/label id label)
(hform/text-field {:required (when required "required")}
id
value))))
(defn render-checkbox [id {:keys [label spec]} values]
(let [value (id values)]
(list
(when-not (field-valid? value spec values)
(spec-to-errmsg label spec value))
(hform/label id label)
(hform/check-box id (some? value) value))))
(defn render-textarea [id {:keys [label spec]} values]
(let [value (id values)]
(list
(when-not (field-valid? value spec values)
(spec-to-errmsg label spec value))
(hform/label id label)
(hform/text-area id value))))
(defn render-select [id {:keys [label spec options]} values]
(let [value (id values)]
(list
(when-not (field-valid? value spec values)
(spec-to-errmsg label spec value))
(hform/label id label)
(hform/drop-down id options value))))
(def render-mapping
{:input render-input
:checkbox render-checkbox
:textarea render-textarea
:select render-select})
(defn cleaned-values
"Removes keys from value map that are not configured in the form"
[form-def values]
(reduce-kv
(fn [agg value-key value]
(if (contains? (:fields form-def) value-key)
(assoc agg value-key value)
agg))
{}
values))
(defn render-form [form-def values]
{:pre [(spec/valid? ::form form-def)]}
(let [cleaned-values (cleaned-values form-def values)]
(conj (map
(fn [[field-id field-def]]
(let [{:keys [options widget]} field-def
widget (cond (some? widget) widget
(some? options) :select
:else :input)
widget-renderer (widget render-mapping)]
(widget-renderer field-id
field-def
cleaned-values)))
(:fields form-def))
(anti-forgery-field))))

@ -13,7 +13,7 @@
:required true
:spec ::domain/name}}})
(def new-attr-form
(def attr-form
{:fields {:name {:label "Name"
:required true
:spec ::attr-domain/name}
@ -26,7 +26,8 @@
["File" "file"]]}
:required {:label "Required"
:required false
:spec ::attr-domain/required}}})
:spec ::attr-domain/required
:widget :checkbox}}})
(defn overview! [req]
(let [session (:session req)
@ -65,14 +66,16 @@
[:h2 "Attributes"]
[:ul
(for [attr attrs]
[:li (:name attr)])]
[:li
(hform/form-to [:post ""]
(form/render-form attr-form attr)
(hform/submit-button "Save"))
(hform/form-to [:delete ""]
(hform/submit-button "Delete!"))])]
[:h3 "New attribute"]
(hform/form-to [:post (path :attribute-new)]
(anti-forgery-field)
(form/render-form attr-form (:params req))
(hform/hidden-field "schema" (:uuid schema))
(form/field new-attr-form :name req)
(form/drop-down new-attr-form :type req)
(form/check-box new-attr-form :required req)
(hform/submit-button "Save"))
[:h2 "Actions"]
(hform/form-to {:class "inline"}

Loading…
Cancel
Save