Skip to content

Instantly share code, notes, and snippets.

@leontalbot
Last active November 6, 2015 19:50
Show Gist options
  • Save leontalbot/1d57bb05c063a989757c to your computer and use it in GitHub Desktop.
Save leontalbot/1d57bb05c063a989757c to your computer and use it in GitHub Desktop.
(ns ^:figwheel-always form.core
(:require
[goog.dom :as gdom]
[om.next :as om :refer-macros [defui]]
[om.dom :as dom]
[cljs.pprint :as pp]))
(enable-console-print!)
(def app-state
(atom
{:poll/questions
[{:id :interest
:type "radio"
:label "Rate your interest in buying this house"
:a [{:value "1" :label "1"}
{:value "2" :label "2"}
{:value "3" :label "3"}
{:value "4" :label "4"}
{:value "5" :label "5"}]}
{:id :reason
:type "checkbox"
:label "Why aren't you interested?"
:a [{:value "already" :label "I just bought a house recently"}
{:value "alternative" :label "I'm am looking for something else"}]}
{:id :shipping-date
:type "checkbox"
:label "When would you be interested in moving in?"
:a [{:value "2016-july" :label "July 2016"}
{:value "2016-fall" :label "Fall 2016"}]}]
:user/selections {}}))
;; -----------------------------------------------------------------------------
;; Helpers
(defn k->s
"keyword to string"
[k]
(->> k str rest (apply str)))
;; -----------------------------------------------------------------------------
;; Parsing
(defmulti read om/dispatch)
(defmethod read :default
[{:keys [state] :as env} key params]
(let [st @state]
(if-let [[_ value] (find st key)]
{:value value}
{:value :not-found})))
(defmethod read :poll/questions
;; I want to update the view so I can see more questions when a radio button
;; in question :interest is toggled.
[{:keys [state]} key {:keys [type id label a]}]
(let [st @state]
{:value (let [ids (condp some [(-> st :user/selections :interest)]
#{"1" "2"} [:interest :reason]
#{"3" "4" "5"} [:interest :shipping-date]
[:interest])]
(filterv #(some (fn [id] (= id (:id %))) ids) (:poll/questions st)))}))
(defmulti mutate om/dispatch)
(defmethod mutate 'selections/update-radio
;; This should update the users selections when radio button is toggled
[{:keys [state]} key {:keys [name value]}]
{:value [:poll/questions]
:action
(fn []
(swap! state assoc-in [:user/selections name] value)
(pp/pprint @state))})
;; -----------------------------------------------------------------------------
;; Components
(defui Question
static om/Ident
(ident [this {:keys [id]}]
[:questions/by-id id])
static om/IQuery
(query [this]
'[:id :type :label :a])
Object
(render [this]
(println "Render Question " (-> this om/props :id))
(let [{:keys [type id label a] :as props} (om/props this)]
(dom/div nil
(dom/h3 nil label)
(apply dom/div nil
(map
(fn [{:keys [label value]}]
(let [name (k->s id)]
(dom/label nil
(dom/input
#js {:type type
:name name
:value value
:onChange
(fn [e]
(om/transact!
this
`[(selections/update-radio
{:name ~id :value ~value}
:poll/questions)]))})
label)))
a))))))
(def question (om/factory Question {:keyfn :id}))
(defui Form
static om/IQuery
(query [this]
(let [subquery (om/get-query Question)]
`[{:poll/questions ~subquery} :user/selections]))
Object
(render [this]
(println "Render Form")
(let [{:keys [poll/questions user/selections] :as props} (om/props this)]
(dom/form #js {:action "/new-houses"}
(apply dom/div nil
(map question questions))
(dom/input #js {:type "submit" :value "Send"})
(dom/p nil (str "state: user/selections: " (om/props this)))))))
;; -----------------------------------------------------------------------------
;; Reconciler
(def parser (om/parser {:read read :mutate mutate}))
(def reconciler
(om/reconciler
{:state app-state
:parser parser}))
(om/add-root! reconciler
Form (gdom/getElement "app"))
@leontalbot
Copy link
Author

Needed to move the :poll/questions out of the () in the transact! call. [(selections/update-radio {:name ~id :value ~value}) :poll/questions] is what we want to pass in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment