Revamped re-frame example

- Flattened into single file

- Changed router to decide which view to render
This commit is contained in:
Valtteri Harmainen 2019-04-25 10:23:55 +03:00
parent 66c6363365
commit 22f38d9992
7 changed files with 142 additions and 159 deletions

View file

@ -1,4 +0,0 @@
(ns frontend-re-frame.config)
(def debug?
^boolean goog.DEBUG)

View file

@ -1,24 +1,157 @@
(ns frontend-re-frame.core
(:require
[reagent.core :as reagent]
[re-frame.core :as re-frame]
[frontend-re-frame.events :as events]
[frontend-re-frame.views :as views]
[frontend-re-frame.config :as config]
[frontend-re-frame.routes :as routes]))
[reagent.core :as reagent]
[reitit.core :as r]
[reitit.coercion :as rc]
[reitit.coercion.spec :as rss]
[reitit.frontend :as rf]
[reitit.frontend.controllers :as rfc]
[reitit.frontend.easy :as rfe]))
;;; Events ;;;
(re-frame/reg-event-db
::initialize-db
(fn [_ _]
{:current-route nil}))
(re-frame/reg-event-fx
::navigate
(fn [db [_ route]]
;; See `navigate` effect in routes.cljs
{::navigate! route}))
(re-frame/reg-event-db
::navigated
(fn [db [_ new-match]]
(assoc db :current-route new-match)))
;;; Subscriptions ;;;
(re-frame/reg-sub
::current-route
(fn [db]
(:current-route db)))
;;; Views ;;;
(defn home-page []
[:div
[:h1 "This is home page"]
[:button
;; Dispatch navigate event that triggers a (side)effect.
{:on-click #(re-frame/dispatch [::navigate ::sub-page2])}
"Go to sub-page 2"]])
(defn sub-page1 []
[:div
[:h1 "This is sub-page 1"]])
(defn sub-page2 []
[:div
[:h1 "This is sub-page 2"]])
;;; Effects ;;;
;; Triggering navigation from events.
(re-frame/reg-fx
::navigate!
(fn [k params query]
(rfe/push-state k params query)))
;;; Routes ;;;
(defn href
"Return relative url for given route. Url can be used in HTML links."
([k]
(href k nil nil))
([k params]
(href k params nil))
([k params query]
(rfe/href k params query)))
(def routes
["/"
[""
{:name ::home
:view home-page
:link-text "Home"
:controllers
[{;; Do whatever initialization needed for home page
;; I.e (re-frame/dispatch [::events/load-something-with-ajax])
:start (fn [& params](js/console.log "Entering home page"))
;; Teardown can be done here.
:stop (fn [& params] (js/console.log "Leaving home page"))}]}]
["sub-page1"
{:name ::sub-page1
:view sub-page1
:link-text "Sub page 1"
:controllers
[{:start (fn [& params] (js/console.log "Entering sub-page 1"))
:stop (fn [& params] (js/console.log "Leaving sub-page 1"))}]}]
["sub-page2"
{:name ::sub-page2
:view sub-page2
:link-text "Sub-page 2"
:controllers
[{:start (fn [& params] (js/console.log "Entering sub-page 2"))
:stop (fn [& params] (js/console.log "Leaving sub-page 2"))}]}]])
(defn on-navigate [new-match]
(let [old-match (re-frame/subscribe [::current-route])]
(when new-match
(let [cs (rfc/apply-controllers (:controllers @old-match) new-match)
m (assoc new-match :controllers cs)]
(re-frame/dispatch [::navigated m])))))
(def router
(rf/router
routes
{:data {:coercion rss/coercion}}))
(defn init-routes! []
(js/console.log "initializing routes")
(rfe/start!
router
on-navigate
{:use-fragment true}))
(defn nav [{:keys [router current-route]}]
(into
[:ul]
(for [route-name (r/route-names router)
:let [route (r/match-by-name router route-name)
text (-> route :data :link-text)]]
[:li
(when (= route-name (-> current-route :data :name))
"> ")
;; Create a normal links that user can click
[:a {:href (href route-name)} text]])))
(defn router-component [{:keys [router]}]
(let [current-route @(re-frame/subscribe [::current-route])]
[:div
[nav {:router router :current-route current-route}]
(when current-route
[(-> current-route :data :view)])]))
;;; Setup ;;;
(def debug? ^boolean goog.DEBUG)
(defn dev-setup []
(when config/debug?
(when debug?
(enable-console-print!)
(println "dev mode")))
(defn mount-root []
(re-frame/clear-subscription-cache!)
(routes/init!) ;; Reset routes on figwheel reload
(reagent/render [views/main-panel]
(init-routes!) ;; Reset routes on figwheel reload
(reagent/render [router-component {:router router}]
(.getElementById js/document "app")))
(defn ^:export init []
(re-frame/dispatch-sync [::events/initialize-db])
(re-frame/dispatch-sync [::initialize-db])
(dev-setup)
(mount-root))

View file

@ -1,4 +0,0 @@
(ns frontend-re-frame.db)
(def default-db
{})

View file

@ -1,20 +0,0 @@
(ns frontend-re-frame.events
(:require
[re-frame.core :as re-frame]
[frontend-re-frame.db :as db]))
(re-frame/reg-event-db
::initialize-db
(fn [_ _]
db/default-db))
(re-frame/reg-event-fx
::navigate
(fn [db [_ route]]
;; See `navigate` effect in routes.cljs
{:frontend-re-frame.routes/navigate route}))
(re-frame/reg-event-db
::navigated
(fn [db [_ new-match]]
(assoc db :current-route new-match)))

View file

@ -1,67 +0,0 @@
(ns frontend-re-frame.routes
(:require [frontend-re-frame.events :as events]
[frontend-re-frame.subs :as subs]
[re-frame.core :as re-frame]
[reitit.coercion :as rc]
[reitit.coercion.spec :as rss]
[reitit.frontend :as rf]
[reitit.frontend.controllers :as rfc]
[reitit.frontend.easy :as rfe]))
;; Effect for triggering navigation from events.
(re-frame/reg-fx
::navigate
(fn [k params query]
(rfe/push-state k params query)))
(defn href
"Return relative url for given route. Url can be used in HTML links."
([k]
(href k nil nil))
([k params]
(href k params nil))
([k params query]
(rfe/href k params query)))
(def routes
["/"
[""
{:name ::home
:human-name "Home"
:controllers
[{;; Do whatever initialization needed for home page
;; I.e (re-frame/dispatch [::events/load-something-with-ajax])
:start (fn [& params](js/console.log "Entering home page"))
;; Teardown can be done here.
:stop (fn [& params] (js/console.log "Leaving home page"))}]}]
["sub-page1"
{:name ::sub-page1
:human-name "Sub page 1"
:controllers
[{:start (fn [& params] (js/console.log "Entering sub-page 1"))
:stop (fn [& params] (js/console.log "Leaving sub-page 1"))}]}]
["sub-page2"
{:name ::sub-page2
:human-name "Sub-page 2"
:controllers
[{:start (fn [& params] (js/console.log "Entering sub-page 2"))
:stop (fn [& params] (js/console.log "Leaving sub-page 2"))}]}]])
(def router
(rf/router
routes
{:data {:coercion rss/coercion}}))
(defn on-navigate [new-match]
(let [old-match (re-frame/subscribe [::subs/current-route])]
(when new-match
(let [cs (rfc/apply-controllers (:controllers @old-match) new-match)
m (assoc new-match :controllers cs)]
(re-frame/dispatch [::events/navigated m])))))
(defn init! []
(js/console.log "initializing routes")
(rfe/start!
router
on-navigate
{:use-fragment true}))

View file

@ -1,8 +0,0 @@
(ns frontend-re-frame.subs
(:require
[re-frame.core :as re-frame]))
(re-frame/reg-sub
::current-route
(fn [db]
(:current-route db)))

View file

@ -1,47 +0,0 @@
(ns frontend-re-frame.views
(:require
[frontend-re-frame.events :as events]
[frontend-re-frame.routes :as routes]
[frontend-re-frame.subs :as subs]
[re-frame.core :as re-frame]))
(defn home-page []
[:div
[:h1 "This is home page"]
[:button
;; Dispatch navigate event that triggers a (side)effect.
{:on-click #(re-frame/dispatch [::events/navigate ::routes/sub-page2])}
"Go to sub-page 2"]])
(defn sub-page1 []
[:div
[:h1 "This is sub-page 1"]])
(defn sub-page2 []
[:div
[:h1 "This is sub-page 2"]])
(defn nav []
(let [current-route (re-frame/subscribe [::subs/current-route])]
[:div
(into
[:ul]
(for [route (->> routes/routes (filter vector?) (map second))
:let [text (-> route :human-name)]]
[:li
(when (= (:name route) (-> @current-route :data :name))
"> ")
;; Create a normal links that user can click
[:a {:href (routes/href (:name route))} text]]))]))
(defn main-panel []
(let [current-route (re-frame/subscribe [::subs/current-route])]
[:div
[nav]
(condp = (-> @current-route :data :name)
::routes/home [home-page]
::routes/sub-page1 [sub-page1]
::routes/sub-page2 [sub-page2]
[:div
[:p (str "Unknown page")]
[:pre @current-route]])]))