Created
December 10, 2014 02:46
-
-
Save awohletz/9edc5f14a86cd370add2 to your computer and use it in GitHub Desktop.
Om routing with Secretary
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 om-routing.core | |
(:require-macros [secretary.core :refer [defroute]] | |
[cljs.core.async.macros :refer [go go-loop]]) | |
(:require [om.core :as om :include-macros true] | |
[om-tools.core :refer-macros [defcomponent]] | |
[sablono.core :as h :refer-macros [html]] | |
[secretary.core :as secretary :include-macros true] | |
[goog.events :as events] | |
[goog.history.EventType :as EventType] | |
[cljs.core.async :refer [put! chan <! pub sub]]) | |
(:import goog.History)) | |
(defonce app-state (atom {:text "Hello Chestnut!"})) | |
(def pub-chan (chan)) | |
(def sub-chan (pub pub-chan :topic)) | |
;Helpers ---------------------------------------------------------------------- | |
(defn consume-events | |
"Consume events from the publication channel. | |
topic is a keyword indicating the topic to subscribe to | |
func takes one arg, the event | |
owner is an Om component" | |
[owner topic func] | |
(let [sub-chan (om/get-shared owner :sub-chan)] | |
(let [event-chan (sub sub-chan topic (chan))] | |
(go-loop [event (<! event-chan)] | |
(func event) | |
(recur (<! event-chan)))))) | |
(defn change-view | |
([view view-name] | |
(put! pub-chan {:topic :change-view | |
:view view | |
:view-name view-name})) | |
([view view-name init-state] | |
(put! pub-chan {:topic :change-view | |
:view view | |
:view-name view-name | |
:view-init-state init-state}))) | |
;Routes ---------------------------------------------------------------------- | |
(declare home-view) | |
(declare about-view) | |
(declare contact-view) | |
(defroute home-path "/" [] | |
(change-view home-view :home-view)) | |
(defroute about-path "/about" [] | |
(change-view about-view :about-view)) | |
(defroute contact-path "/contact" [] | |
(change-view contact-view :contact-view)) | |
;Components ---------------------------------------------------------------------- | |
(defcomponent home-view [app owner] | |
(render [_] | |
(html [:p "Home page"]))) | |
(defcomponent about-view [app owner] | |
(render [_] | |
(html [:p "About page"]))) | |
(defcomponent contact-view [app owner] | |
(render [_] | |
(html [:p "Contact page"]))) | |
(defn menu [& content] | |
[:span [:ul | |
[:li [:a {:href (home-path)} "Home"] ] | |
[:li [:a {:href (about-path)} "About"]] | |
[:li [:a {:href (contact-path)} "Contact"]]] | |
[:hr] | |
[:div.main-section content] | |
[:hr] | |
[:div.footer | |
[:p "Copyright"]]]) | |
(defcomponent root-view [app owner] | |
(init-state [_] | |
{:view home-view}) | |
(did-mount [_] | |
(consume-events owner :change-view | |
(fn [{:keys [view view-init-state view-name]}] | |
(om/set-state! owner :view view) | |
(om/set-state! owner :view-init-state view-init-state) | |
(om/set-state! owner :react-key view-name)))) | |
(render-state [_ {:keys [view view-init-state react-key]}] | |
(html | |
(menu | |
(om/build view app {:init-state view-init-state :react-key react-key}))))) | |
;Config ---------------------------------------------------------------------- | |
(defn main [] | |
(om/root | |
root-view | |
app-state | |
{:target (. js/document (getElementById "app")) | |
:shared {:sub-chan sub-chan | |
:pub-chan pub-chan}})) | |
;Fallback for browsers without HTML5 History | |
(secretary/set-config! :prefix "#") | |
;Set Secretary to listen to navigation events (i.e. HTML5 History events) | |
(let [h (History.)] | |
(goog.events/listen h EventType/NAVIGATE #(secretary/dispatch! (.-token %))) | |
(doto h (.setEnabled true))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment