This is the example that comes with the reagent template converted to use HTML5 based history. This means there are no #
in the urls.
I just got this working, so there might be better approaches
The changes are
- use
goog.history.Html5history
instead ofgoog.History
- listen to clicks on the page, extract the path from them, and push them onto the history
- listen to history changes, and have secretary do its thing in response
(ns routing.core
(:require [reagent.core :as reagent :refer [atom]]
[reagent.session :as session]
[secretary.core :as secretary :include-macros true]
[goog.events :as events]
[goog.history.EventType :as EventType])
(:import goog.history.Html5History
goog.Uri))
;; -------------------------
;; Views
(defn home-page []
[:div [:h2 "Welcome to routing"]
[:div [:a {:href "/about"} "go to about page"]]])
(defn about-page []
[:div [:h2 "About routing"]
[:div [:a {:href "/"} "go to the home page"]]])
(defn current-page []
[:div [(session/get :current-page)]])
;; -------------------------
;; Routes
(secretary/defroute "/" []
(session/put! :current-page home-page))
(secretary/defroute "/about" []
(session/put! :current-page about-page))
;; -------------------------
;; Initialize app
(defn init! []
(reagent/render-component [current-page] (.getElementById js/document "app")))
;; -------------------------
;; History
(defn hook-browser-navigation! []
(let [history (doto (Html5History.)
(events/listen
EventType/NAVIGATE
(fn [event]
(secretary/dispatch! (.-token event))))
(.setUseFragment false)
(.setPathPrefix "")
(.setEnabled true))]
(events/listen js/document "click"
(fn [e]
(. e preventDefault)
(let [path (.getPath (.parse Uri (.-href (.-target e))))
title (.-title (.-target e))]
(when path
(. history (setToken path title))))))))
;; need to run this after routes have been defined
(hook-browser-navigation!)
Thanks for this, it works wonderfully. It's great to be able to do an implementation then see how someone else has done it, makes you learn a few things :)