Last active
February 20, 2016 12:46
-
-
Save ThomasDeutsch/0c1e8e4ac6627ce93ae5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns scheduler.devcards.omnexttest | |
(:require | |
[devcards.core] | |
[om.next :as om :refer-macros [defui ui]] | |
[om.dom :as dom :include-macros true]) | |
(:require-macros | |
[devcards.core :as dc :refer [defcard defcard-doc defcard-om-next noframe-doc deftest dom-node]])) | |
(defcard-doc | |
"## Navigation with Toggle | |
With a click of a button (Nav component), you can select a movie. | |
The movie details will be shown (MovieDetails component). | |
If you click on a already selected movie, the movie-detais view will toggle. | |
In case no movie-details should be displayed, the reader will return `:not-found` and the | |
`mount->` function will not place the component in the roots render function. | |
### Problem: root gets rendered twice, in case a movie-details component will not be rendered. | |
open the console to see when the root gets rendered. | |
") | |
;; ===================================================================================================================== | |
;; State | |
(def test-data (atom {:movie-by-id {"movie-1" {:id "movie-1" | |
:title "Pulp Fiction" | |
:year 1994} | |
"movie-2" {:id "movie-2" | |
:title "The Matrix" | |
:year 1999}} | |
:movies [[:movie-by-id "movie-1"] | |
[:movie-by-id "movie-2"]] | |
:selected-movie [:movie-by-id "movie-1"]})) | |
;; ===================================================================================================================== | |
;; Helper fn | |
;; if reader returns :not-found, to not render a given component. | |
(defn mount-> [d component] | |
(if (= d :not-found) | |
nil | |
(component d))) | |
;; ===================================================================================================================== | |
;; Mutate | |
(defmulti mutate om/dispatch) | |
(defmethod mutate 'movie/select | |
[{:keys [state]} _ {:keys [item-id]}] | |
{:action | |
(fn [] | |
(let [st @state] | |
(if (= (second (:selected-movie st)) item-id) | |
(swap! state assoc-in [:selected-movie] nil) | |
(swap! state assoc-in [:selected-movie] [:movie-by-id item-id]))))}) | |
;; ===================================================================================================================== | |
;; Read | |
(defmulti read om/dispatch) | |
(defmethod read :nav | |
[{:keys [query state]} k _] | |
(let [st @state] | |
{:value (om/db->tree query (get st k) st)})) | |
(defmethod read :movie-details | |
[{:keys [query state]} k _] | |
(let [st @state] | |
{:value (if (some? (:selected-movie st)) | |
(om/db->tree query (:selected-movie st) st) | |
:not-found)})) | |
;; ===================================================================================================================== | |
;; Components | |
(defui ^:once Nav | |
static om/IQuery | |
(query [this] | |
'[[:movie-by-id _] | |
[:selected-movie _]]) | |
Object | |
(render [this] | |
(let [{:keys [movie-by-id selected-movie]} (om/props this)] | |
(dom/ul #js{:className "item-list"} | |
(->> (vals movie-by-id) | |
(map (fn [item] | |
(dom/div nil | |
(dom/button #js{:style (if (= (:id selected-movie) (:id item)) #js{:backgroundColor "yellow"}) | |
:onClick (fn [e] (om/transact! this `[(movie/select ~{:item-id (:id item)}) :selected-movie]))} | |
(:title item)))))))))) | |
(def c-nav (om/factory Nav {})) | |
(defui ^:once MovieDetails | |
static om/IQuery | |
(query [this] | |
'[:title :year]) | |
Object | |
(render [this] | |
(let [{:keys [title year]} (om/props this)] | |
(dom/h3 #js{:className "item-details"} | |
(dom/div nil "Title: " title) | |
(dom/div nil "Year: " year))))) | |
(def c-movie-details (om/factory MovieDetails {})) | |
(defui ^:once Root | |
static om/IQuery | |
(query [this] | |
[{:nav (om/get-query Nav)} | |
{:movie-details (om/get-query MovieDetails)}]) | |
Object | |
(render [this] | |
(println "render root") | |
(let [{:keys [nav movie-details]} (om/props this)] | |
(dom/div nil | |
(mount-> nav c-nav) ;use of the mount-> helper function | |
(mount-> movie-details c-movie-details))))) | |
(defonce reconciler | |
(om/reconciler {:state test-data | |
:parser (om/parser {:read read | |
:mutate mutate})})) | |
(defcard navigation-with-toggle | |
(dc/om-next-root Root reconciler)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment