From dad8f530a672aa86a695b376f2295b8095d686d9 Mon Sep 17 00:00:00 2001 From: Juho Teperi Date: Fri, 24 Mar 2023 11:32:22 +0200 Subject: [PATCH] Add example and update docs --- doc/frontend/browser.md | 12 +++++++++-- .../src/frontend/core.cljs | 21 ++++++++++++------- .../reitit-frontend/src/reitit/frontend.cljs | 16 +++++++------- .../src/reitit/frontend/history.cljs | 8 +++---- 4 files changed, 36 insertions(+), 21 deletions(-) diff --git a/doc/frontend/browser.md b/doc/frontend/browser.md index 50349fcc..1541265b 100644 --- a/doc/frontend/browser.md +++ b/doc/frontend/browser.md @@ -2,8 +2,16 @@ Reitit includes two browser history integrations. -Functions follow HTML5 History API: `push-state` to change route, `replace-state` -to change route without leaving previous entry in browser history. +Main functions are `navigate` and `set-query`. Navigate is used to navigate +to named routes, and the options parameter can be used to control all +parameters and if `pushState` or `replaceState` should be used to control +browser history stack. The `set-query` function can be used to change +or modify query parameters for the current route, it takes either map of +new query params or function from old params to the new params. + +There are also secondary functions following HTML5 History API: +`push-state` to navigate to new route adding entry to the history and +`replace-state` to change route without leaving previous entry in browser history. ## Fragment router diff --git a/examples/frontend-controllers/src/frontend/core.cljs b/examples/frontend-controllers/src/frontend/core.cljs index 60cd6f17..6a2388f2 100644 --- a/examples/frontend-controllers/src/frontend/core.cljs +++ b/examples/frontend-controllers/src/frontend/core.cljs @@ -19,10 +19,17 @@ [:ul [:li [:a {:href (rfe/href ::item {:id 1})} "Item 1"]] [:li [:a {:href (rfe/href ::item {:id 2} {:foo "bar"})} "Item 2"]]] - (if id + (when id [:h2 "Selected item " id]) - (if (:foo query) - [:p "Optional foo query param: " (:foo query)])])) + [:p "Query params: " [:pre (pr-str query)]] + [:ul + [:li [:a {:on-click #(rfe/set-query {:a 1})} "set a=1"]] + [:li [:a {:on-click #(rfe/set-query {:a 2} {:replace true})} "set a=2 and replaceState"]] + [:li [:a {:on-click (fn [_] (rfe/set-query #(assoc % :foo "zzz")))} "add foo=zzz"]]] + [:button + {:on-click #(rfe/navigate ::item {:path-params {:id 3} + :query-params {:foo "aaa"}})} + "Navigate example, go to item 3"]])) (defonce match (r/atom nil)) @@ -31,9 +38,8 @@ [:ul [:li [:a {:href (rfe/href ::frontpage)} "Frontpage"]] [:li - [:a {:href (rfe/href ::item-list)} "Item list"] - ]] - (if @match + [:a {:href (rfe/href ::item-list)} "Item list"]]] + (when @match (let [view (:view (:data @match))] [view @match])) [:pre (with-out-str (fedn/pprint @match))]]) @@ -63,7 +69,8 @@ ["/:id" {:name ::item :parameters {:path {:id s/Int} - :query {(s/optional-key :foo) s/Keyword}} + :query {(s/optional-key :a) s/Int + (s/optional-key :foo) s/Keyword}} :controllers [{:parameters {:path [:id]} :start (fn [{:keys [path]}] (js/console.log "start" "item controller" (:id path))) diff --git a/modules/reitit-frontend/src/reitit/frontend.cljs b/modules/reitit-frontend/src/reitit/frontend.cljs index 89b41fc0..38608e13 100644 --- a/modules/reitit-frontend/src/reitit/frontend.cljs +++ b/modules/reitit-frontend/src/reitit/frontend.cljs @@ -1,11 +1,11 @@ (ns reitit.frontend (:require [clojure.set :as set] [reitit.coercion :as coercion] - [reitit.core :as r]) - (:import goog.Uri - goog.Uri.QueryData)) + [reitit.core :as r] + goog.Uri + goog.Uri.QueryData)) -(defn- query-param [^QueryData q k] +(defn- query-param [^goog.uri.QueryData q k] (let [vs (.getValues q k)] (if (< (alength vs) 2) (aget vs 0) @@ -13,7 +13,7 @@ (defn query-params "Given goog.Uri, read query parameters into a Clojure map." - [^Uri uri] + [^goog.Uri uri] (let [q (.getQueryData uri)] (->> q (.getKeys) @@ -26,11 +26,11 @@ Note: coercion is not applied to the query params" [path new-query-or-update-fn] - (let [^goog.Uri uri (Uri/parse path) + (let [^goog.Uri uri (goog.Uri/parse path) new-query (if (fn? new-query-or-update-fn) (new-query-or-update-fn (query-params uri)) new-query-or-update-fn)] - (.setQueryData uri (QueryData/createFromMap (clj->js new-query))) + (.setQueryData uri (goog.Uri.QueryData/createFromMap (clj->js new-query))) (.toString uri))) (defn match-by-path @@ -40,7 +40,7 @@ :on-coercion-error - a sideeffecting fn of `match exception -> nil`" ([router path] (match-by-path router path nil)) ([router path {:keys [on-coercion-error]}] - (let [uri (.parse Uri path) + (let [uri (.parse goog.Uri path) coerce! (if on-coercion-error (fn [match] (try (coercion/coerce! match) diff --git a/modules/reitit-frontend/src/reitit/frontend/history.cljs b/modules/reitit-frontend/src/reitit/frontend/history.cljs index 3cbec5ab..5764e10f 100644 --- a/modules/reitit-frontend/src/reitit/frontend/history.cljs +++ b/modules/reitit-frontend/src/reitit/frontend/history.cljs @@ -3,8 +3,8 @@ events." (:require [goog.events :as gevents] [reitit.core :as reitit] - [reitit.frontend :as rf]) - (:import goog.Uri)) + [reitit.frontend :as rf] + goog.Uri)) (defprotocol History (-init [this] "Create event listeners") @@ -78,7 +78,7 @@ the page location is updated using History API." [router e el uri] (let [current-domain (if (exists? js/location) - (.getDomain (.parse Uri js/location)))] + (.getDomain (.parse goog.Uri js/location)))] (and (or (and (not (.hasScheme uri)) (not (.hasDomain uri))) (= current-domain (.getDomain uri))) (not (.-altKey e)) @@ -109,7 +109,7 @@ ignore-anchor-click (fn [e] ;; Returns the next matching ancestor of event target (when-let [el (closest-by-tag (event-target e) "a")] - (let [uri (.parse Uri (.-href el))] + (let [uri (.parse goog.Uri (.-href el))] (when (ignore-anchor-click-predicate router e el uri) (.preventDefault e) (let [path (str (.getPath uri)