Add frontend-controllers example

This commit is contained in:
Juho Teperi 2018-07-11 13:19:24 +03:00
parent 8971c8fd2b
commit 82f8aaa8cf
9 changed files with 182 additions and 16 deletions

View file

@ -0,0 +1 @@
../../../modules/reitit-core

View file

@ -0,0 +1 @@
../../../modules/reitit-frontend

View file

@ -0,0 +1 @@
../../../modules/reitit-schema

View file

@ -0,0 +1,52 @@
(defproject frontend "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.9.0"]
[ring-server "0.5.0"]
[reagent "0.8.1"]
[ring "1.6.3"]
[compojure "1.6.1"]
[hiccup "1.0.5"]
[org.clojure/clojurescript "1.10.339"]
[metosin/reitit "0.1.4-SNAPSHOT"]
[metosin/reitit-schema "0.1.4-SNAPSHOT"]
[metosin/reitit-frontend "0.1.4-SNAPSHOT"]
;; Just for pretty printting the match
[fipp "0.6.12"]]
:plugins [[lein-cljsbuild "1.1.7"]
[lein-figwheel "0.5.16"]]
:source-paths []
:resource-paths ["resources" "target/cljsbuild"]
:profiles {:dev {:dependencies [[binaryage/devtools "0.9.10"]]}}
:cljsbuild
{:builds
[{:id "app"
:figwheel true
:source-paths ["src"]
:watch-paths ["src" "checkouts/reitit-frontend/src"]
:compiler {:main "frontend.core"
:asset-path "/js/out"
:output-to "target/cljsbuild/public/js/app.js"
:output-dir "target/cljsbuild/public/js/out"
:source-map true
:optimizations :none
:pretty-print true
:preloads [devtools.preload]}}
{:id "min"
:source-paths ["src"]
:compiler {:output-to "target/cljsbuild/public/js/app.js"
:output-dir "target/cljsbuild/public/js"
:source-map "target/cljsbuild/public/js/app.js.map"
:optimizations :advanced
:pretty-print false}}]}
:figwheel {:http-server-root "public"
:server-port 3449
:nrepl-port 7002})

View file

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<title>Reitit frontend example</title>
</head>
<body>
<div id="app"></div>
<script src="js/app.js"></script>
</body>
</html>

View file

@ -0,0 +1,95 @@
(ns frontend.core
(:require [reagent.core :as r]
[reitit.core :as re]
[reitit.frontend :as rf]
[reitit.frontend.history :as rfh]
[reitit.frontend.controllers :as rfc]
[reitit.coercion :as rc]
[reitit.coercion.schema :as rsc]
[schema.core :as s]
[fipp.edn :as fedn]))
(defonce history (atom nil))
(defn home-page []
[:div
[:h2 "Welcome to frontend"]
[:p "Look at console log for controller calls."]])
(defn item-page [match]
(let [{:keys [path query]} (:parameters match)
{:keys [id]} path]
[:div
[:ul
[:li [:a {:href (rfh/href @history ::item {:id 1})} "Item 1"]]
[:li [:a {:href (rfh/href @history ::item {:id 2} {:foo "bar"})} "Item 2"]]]
(if id
[:h2 "Selected item " id])
(if (:foo query)
[:p "Optional foo query param: " (:foo query)])]))
(defonce match (r/atom nil))
(defn current-page []
[:div
[:ul
[:li [:a {:href (rfh/href @history ::frontpage)} "Frontpage"]]
[:li
[:a {:href (rfh/href @history ::item-list)} "Item list"]
]]
(if @match
(let [view (:view (:data @match))]
[view @match]))
[:pre (with-out-str (fedn/pprint @match))]])
(defn log-fn [& params]
(fn [_]
(apply js/console.log params)))
(def routes
(re/router
["/"
[""
{:name ::frontpage
:view home-page
:controllers [{:start (log-fn "start" "frontpage controller")
:stop (log-fn "stop" "frontpage controller")}]}]
["items"
;; Shared data for sub-routes
{:view item-page
:controllers [{:start (log-fn "start" "items controller")
:stop (log-fn "stop" "items controller")}]}
[""
{:name ::item-list
:controllers [{:start (log-fn "start" "item-list controller")
:stop (log-fn "stop" "item-list controller")}]}]
["/:id"
{:name ::item
:parameters {:path {:id s/Int}
:query {(s/optional-key :foo) s/Keyword}}
:controllers [{:params (fn [match]
(:path (:parameters match)))
:start (fn [params]
(js/console.log "start" "item controller" (:id params)))
:stop (fn [params]
(js/console.log "stop" "item controller" (:id params)))}]}]]]
{:compile rc/compile-request-coercers
:data {:controllers [{:start (log-fn "start" "root-controller")
:stop (log-fn "stop" "root controller")}]
:coercion rsc/coercion}}))
(defn init! []
(swap! history (fn [old-history]
(rfh/stop! old-history)
(rfh/start!
routes
(fn [new-match]
(swap! match (fn [old-match]
(if new-match
(assoc new-match :controllers (rfc/apply-controllers (:controllers old-match) new-match))))))
{:use-fragment true
:path-prefix "/"})))
(r/render [current-page] (.getElementById js/document "app")))
(init!)

View file

@ -8,7 +8,7 @@
[schema.core :as s]
[fipp.edn :as fedn]))
(def router (atom nil))
(defonce history (atom nil))
(defn home-page []
[:div
@ -19,8 +19,8 @@
[:h2 "About frontend"]
[:ul
[:li [:a {:href "http://google.com"} "external link"]]
[:li [:a {:href (rfh/href @router ::foobar)} "Missing route"]]
[:li [:a {:href (rfh/href @router ::item)} "Missing route params"]]]])
[:li [:a {:href (rfh/href @history ::foobar)} "Missing route"]]
[:li [:a {:href (rfh/href @history ::item)} "Missing route params"]]]])
(defn item-page [match]
(let [{:keys [path query]} (:parameters match)
@ -35,10 +35,10 @@
(defn current-page []
[:div
[:ul
[:li [:a {:href (rfh/href @router ::frontpage)} "Frontpage"]]
[:li [:a {:href (rfh/href @router ::about)} "About"]]
[:li [:a {:href (rfh/href @router ::item {:id 1})} "Item 1"]]
[:li [:a {:href (rfh/href @router ::item {:id 2} {:foo "bar"})} "Item 2"]]]
[:li [:a {:href (rfh/href @history ::frontpage)} "Frontpage"]]
[:li [:a {:href (rfh/href @history ::about)} "About"]]
[:li [:a {:href (rfh/href @history ::item {:id 1})} "Item 1"]]
[:li [:a {:href (rfh/href @history ::item {:id 2} {:foo "bar"})} "Item 2"]]]
(if @match
(let [view (:view (:data @match))]
[view @match]))
@ -62,10 +62,12 @@
:data {:coercion rsc/coercion}}))
(defn init! []
(reset! router (rfh/start! routes
(fn [m] (reset! match m))
{:use-fragment true
:path-prefix "/"}))
(swap! history (fn [old-history]
(rfh/stop! old-history)
(rfh/start! routes
(fn [m] (reset! match m))
{:use-fragment true
:path-prefix "/"})))
(r/render [current-page] (.getElementById js/document "app")))
(init!)

View file

@ -22,9 +22,9 @@
those previously enabled. Resets controllers whose
parameters have changed."
[old-controllers new-match]
(let [new-controllers (map (fn [controller]
(assoc controller ::params (get-params controller new-match)))
(:controllers (:data new-match)))
(let [new-controllers (mapv (fn [controller]
(assoc controller ::params (get-params controller new-match)))
(:controllers (:data new-match)))
changed-controllers (->> (map (fn [old new]
;; different controllers, or params changed
(if (not= old new)

View file

@ -57,7 +57,11 @@
(.replaceToken history (path->token history (.getPath uri)))))))
(defn start!
"Parameters:
"This registers event listeners on either haschange or HTML5 history.
When using with development workflow like Figwheel, rememeber to
remove listeners using stop! call before calling start! again.
Parameters:
- router The reitit routing tree.
- on-navigate Function to be called when route changes.
@ -94,7 +98,7 @@
:close-fn (fn []
(e/unlistenByKey event-key)
(e/unlistenByKey click-listen-key)
(.setEnabled history false))}))
(.dispose history))}))
(defn stop! [{:keys [close-fn]}]
(if close-fn