Skip to content

Instantly share code, notes, and snippets.

@scttnlsn
Last active July 2, 2016 07:36
Show Gist options
  • Save scttnlsn/7018b128032b73ce187e to your computer and use it in GitHub Desktop.
Save scttnlsn/7018b128032b73ce187e to your computer and use it in GitHub Desktop.
Om/Secretary nested routing
(ns nested-routing.core
(:require-macros [om.core :as om]
[secretary.core :refer [defroute]])
(:require [om.dom :as dom]
[om.core :as om]
[secretary.core :as secretary]
[goog.events :as events]
[goog.history.EventType :as EventType])
(:import goog.History))
(declare app-state
home-path
posts-path
post-path
outlet)
(defn outlet [data owner]
(let [{:keys [current-route route-components]} (om/get-shared owner)
index (or (om/get-state owner :outlet-index) 0)
[route _] (om/observe owner (current-route))
components (get route-components route)]
(if (> (count components) index)
(let [component (nth components index)]
(om/build component data {:state {:outlet-index (inc index)}}))
nil)))
(defn root [data owner]
(om/component (outlet data owner)))
;; components
(defn home [data owner]
(om/component
(dom/a #js {:href (posts-path)} "View posts")))
(defn post-item [{:keys [title] :as data} owner]
(om/component
(dom/li nil
(dom/a #js {:href (post-path data)} title))))
(defn posts [{:keys [posts] :as data} owner]
(om/component
(dom/div nil
(dom/a #js {:href (posts-path)} "Posts:")
(apply dom/ul nil
(om/build-all post-item posts))
(or
(outlet data owner)
(dom/p nil "No post selected")))))
(defn post-detail [{:keys [posts route]} owner]
(om/component
(let [[_ {:keys [id]}] route
{:keys [title details]} (first (filter #(= (:id %) id) posts))]
(dom/p nil details))))
(defn main [data owner]
(om/component
(dom/div nil
(dom/h1 nil
(dom/a #js {:href (home-path)} "Nested Routing Example"))
(outlet data owner))))
;; routing
(def route-components
{:home [main home]
:post-list [main posts]
:post-detail [main posts post-detail]})
(defroute home-path "/" []
(swap! app-state assoc :route [:home {}]))
(defroute posts-path "/posts" []
(swap! app-state assoc :route [:post-list {}]))
(defroute post-path "/posts/:id" [id]
(swap! app-state assoc :route [:post-detail {:id (js/parseInt id 10)}]))
(defn current-route []
(om/ref-cursor (:route (om/root-cursor app-state))))
;; main
(enable-console-print!)
(def app-state (atom {:route [:home {}]
:posts [{:id 1
:title "Lorem ipsum"
:details "Lorem ipsum dolor sit amet, consectetur adipiscing elit."}
{:id 2
:title "Morbi porta"
:details "Morbi porta tortor mauris, sit amet tincidunt libero malesuada nec."}]}))
(secretary/set-config! :prefix "#")
(let [h (History.)]
(goog.events/listen h EventType/NAVIGATE #(secretary/dispatch! (.-token %)))
(doto h (.setEnabled true)))
(om/root root
app-state
{:target (. js/document (getElementById "app"))
:shared {:current-route current-route
:route-components route-components}})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment