Form Validation with Clojure Spec

8
Form Validation with Clojure Spec Alexander Kiel Clojure Meetup Leipzig 2017

Transcript of Form Validation with Clojure Spec

Form Validation with Clojure Spec

Alexander KielClojure Meetup Leipzig 2017

General Idea

• We like to use the same specs for validating user input and for server-side validation

• We use an error-formatter to generate human-readable error messages from explain-data

Error Formatter• multi-method with hierarchic dispatch on

[normalized-pred id via] [normalized-pred id] [normalized-pred]

• Predicates are normalised by removing all numbers

(<= (count %) 10) ==> (<= (count %))

• default error formatters are available

• no need to write an error formatter for each input

Default Error Formatters;; Matches on (not (blank? %)) predicate (defmethod error-formatter '[(not (blank? %))] [_ _] "Wert erforderlich”)

;; Matches on normalised (<= (count %)) predicate and ;; uses full predicate and val from problem for error msg (defmethod error-formatter '[(<= (count %))] [_ {:keys [pred val]}] (let [max-length (last pred)] (gstr/format "Maximale Länge von %s Zeichen um %s Zeichen überschritten" max-length (- (count val) max-length))))

Match Error Formatters by ID

(defmethod error-formatter '[(re-matches %)] [_ _] "Ungültiger Barcode.")

(defmethod error-formatter '[(re-matches %) "in-insert-pos"] [_ _] "Ungültige Position.")

(defmethod error-formatter '[(re-matches %) "out-group-id"] [_ _] "Ungültige Gruppe.")

Usage in TextField• TextField uses default error formatters which match

the used predicate.

(s/def ::name #(not (blank? %))) (form/validating-text-field {:id "sso-name" :auto-focus true :floating-label-text "Name" :spec ::name :on-change #(update-order! ::name %)})

Conforming Values• one can normalise input values through s/conform

• in this example, users don’t have to input positions uppercase

(def upper-case-conformer (s/conformer (fn [x] (if (string? x) (str/upper-case x) ::s/invalid))))

;; A 2D position from A1 to D7 (s/def ::pos (s/and upper-case-conformer #(re-matches #"[A-D][1-7]" %)))

GitHub Project

https://github.com/alexanderkiel/material-comp