Skip to content

Instantly share code, notes, and snippets.

@ThomasDeutsch
Last active November 21, 2015 09:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ThomasDeutsch/0080e4ec0a0a21bec943 to your computer and use it in GitHub Desktop.
Save ThomasDeutsch/0080e4ec0a0a21bec943 to your computer and use it in GitHub Desktop.
(ns om-tutorial.core
(:require
[goog.dom :as gdom]
[om.next :as om :refer-macros [defui]]
[datascript.core :as d]
[om.dom :as dom]))
(enable-console-print!)
;; -----------------------------------------------------------------------------
;; DB
(def conn (d/create-conn {:list/one {:db/valueType :db.type/ref
:db/cardinality :db.cardinality/many}
:list/two {:db/valueType :db.type/ref
:db/cardinality :db.cardinality/many}}))
(d/transact! conn
[{:db/id -1
:name "John"
:points 0}
{:db/id -2
:name "Mary"
:points 0
:age 27}
{:db/id -3
:name "Bob"
:points 0}
{:db/id -4
:name "Gwen"
:points 0}
{:db/id -5
:name "Jeff"
:points 0}
;; root entity 0 will contain the two lists
;; as far as i know, this is not possible in datomic, but in datascript it is
;; a nice solution. See todo datascript app:
;; https://github.com/tonsky/datascript-todo/blob/gh-pages/src/datascript_todo/core.cljs#L38
;; Because of this, i do not need to find the root entity. I can savely assume it is :db/id 0
{:db/id 0
:list/one [-1 -2 -3]
:list/two [-2 -4 -5]}])
;; -----------------------------------------------------------------------------
;; Parsing
(defmulti read om/dispatch)
(defn get-people [state key]
(let [st @state]
(into [] (map #(get-in st %)) (get st key))))
(defmethod read :list/one
[{:keys [state query _ _]} key _]
{:value (-> (d/pull @state [{key query}] 0)
(get key))})
(defmethod read :list/two
[{:keys [state query _ _]} key _]
{:value (-> (d/pull @state [{key query}] 0)
(get key))})
(defmulti mutate om/dispatch)
(defmethod mutate 'points/increment
[{:keys [state]} _ {:keys [db/id points]}]
{:action
(fn []
(d/transact! state [[:db/add id :points (inc points)]]))})
(defmethod mutate 'points/decrement
[{:keys [state]} _ {:keys [db/id points]}]
{:action
(fn []
(d/transact! state [[:db/add id :points (dec points)]]))})
;; -----------------------------------------------------------------------------
;; Components
(defui Person
static om/Ident
(ident [this {:keys [db/id]}]
[:db/id id])
static om/IQuery
(query [this]
'[:db/id :name :points :age])
Object
(render [this]
(println "Render Person" (-> this om/props :name))
(let [{:keys [points name foo] :as props} (om/props this)]
(dom/li nil
(dom/label nil (str name ", points: " points))
(dom/button
#js {:onClick
(fn [e]
(om/transact! this
`[(points/increment ~props)]))}
"+")
(dom/button
#js {:onClick
(fn [e]
(om/transact! this
`[(points/decrement ~props)]))}
"-")))))
(def person (om/factory Person {:keyfn :name}))
(defui ListView
Object
(render [this]
(println "Render ListView" (-> this om/path first))
(let [list (om/props this)]
(apply dom/ul nil
(map person list)))))
(def list-view (om/factory ListView))
(defui RootView
static om/IQuery
(query [this]
(let [subquery (om/get-query Person)]
`[{:list/one ~subquery} {:list/two ~subquery}]))
Object
(render [this]
(println "Render RootView")
(let [{:keys [list/one list/two]} (om/props this)]
(apply dom/div nil
[(dom/h2 nil "List A")
(list-view one)
(dom/h2 nil "List B")
(list-view two)]))))
(def reconciler
(om/reconciler
{:state conn
:parser (om/parser {:read read :mutate mutate})}))
(om/add-root! reconciler
RootView (gdom/getElement "app"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment