Skip to content
This repository has been archived by the owner on Feb 9, 2023. It is now read-only.

district0x/district-ui-router

Repository files navigation

district-ui-router

CircleCI Clojars Project

Clojurescript re-mount module, that provides routing functionality for UI. This module currently utilises a forked bide routing library. It also provides 2 reagent components helpful for switching pages in UI based on currently active page.

Installation

Add [district0x/district-ui-router "VERSION"] into your project.clj

Include [district.ui.router] in your CLJS file, where you use mount/start

API Overview

Warning: district0x modules are still in early stages, therefore API can change in a future.

district.ui.router

This namespace contains router mount module.

You can pass following args to initiate this module:

  • :routes Routes as you'd pass them into bide library
  • :default-route Default route, passed as :default into bide library.
  • :html5? Pass true if you want to use HTML5 history. This option overrides :html5-hosts.
  • :html5-hosts Collection of hostnames for which HTML5 history should be used. You can also pass string of comma separated
  • :scroll-top? When true will scroll window to top after navigation hostnames instead of collection. This is useful for defining hostnames in project.clj via :closure-defines.
  (ns my-district.core
    (:require [mount.core :as mount]
              [district.ui.router]))

  (-> (mount/with-args
        {:router {:routes [["/a" :route/a]
                           ["/b/:b" :route/b]]
                  :default-route :route/a
                  :html5-hosts ["localhost" "mydomain.com"]}})
    (mount/start))

district.ui.router.subs

re-frame subscriptions provided by this module:

Returns active page. A map containing :name :params :query.

Returns route name of active page.

Returns params of active page.

Returns query of active page.

Works as bide's resolve, but you don't need to pass router.

Works as bide's match, but you don't need to pass router.

Return's bide's router.

True if using HTML5 History.

district.ui.router.events

re-frame events provided by this module:

Event fired when active page has been changed. Use this event to hook into event flow.

Event to call ::watch-active-page effect.

Event to call ::unwatch-active-page effect.

Event to call ::navigate effect.

Event to call ::replace effect.

district.ui.router.effects

re-frame effects provided by this module

This is special type of effect useful for hooking into active-page-changed event. Works similarly as re-frame-forward-events-fx, but instead of dispatching being based on events, it is based on route name, params and query. This is useful when, for example, your module needs to load data when user visits certain page.

As a param you pass collection of maps containing following keys:

  • :id ID of watcher, so you can later unwatch using this ID
  • :name Route name dispatching will be based on. You can pass also collection of routes or a predicate function.
  • :params Route params dispatching will be based on. You can also pass predicate function.
  • :query Route query dispatching will be based on. You can also pass predicate function.
  • :dispatch Dispatch fired when certain name/params/query is hit. Fired event will get name, params, query as last 3 args.
  • :dispatch-n Dispatches fired when certain name/params/query is hit.

You can do dispatching based on either name, params or query, or any combination of two or three of them.

(ns my.district
  (:require
    [district.ui.router.effects :as router-effects]
    [re-frame.core :refer [reg-event-fx]]))


(reg-event-fx
  ::my-event
  (fn []
    ;; When :route/b page is visited ::some-event will be fired
    {::router-effects/watch-active-page [{:id :watcher1
                                          :name :route/b
                                          :dispatch [::some-event]}]}))

(reg-event-fx
  ::my-event
  (fn []
    ;; When :route/c page with {:a 1} params is visited ::some-event will be fired
    {::router-effects/watch-active-page [{:id :watcher1
                                          :name :route/c
                                          :params {:a 1}
                                          :dispatch [::some-event]}]}))

(reg-event-fx
  ::my-event
  (fn []
    ;; When any page with {:some-param "abc"} query is visited ::some-event will be fired
    {::router-effects/watch-active-page [{:id :watcher1
                                          :query {:some-param "abc"}
                                          :dispatch [::some-event]}]}))

Unwatches previously set watcher based on :id.

(reg-event-fx
  ::my-event
  (fn []
    {::router-effects/unwatch-active-page [{:id :watcher1}]}))

Reframe effect to call bide's navigate! function.

Reframe effect to call bide's replace! function.

district.ui.router.queries

DB queries provided by this module: You should use them in your events, instead of trying to get this module's data directly with get-in into re-frame db.

Works the same way as sub ::active-page

Works the same way as sub ::active-page-name

Works the same way as sub ::active-page-params

Works the same way as sub ::active-page-query

Associates new active-page and returns new re-frame db.

Works the same way as sub ::resolve

Works the same way as sub ::match

Works the same way as sub ::bide-router

Works the same way as sub ::html5?

Associates new bide router and returns new re-frame db.

Associates whether the module is using html5 history or not.

district.ui.router.utils

Util functions provided by this module:

Serves as a wrapper for instantly derefed sub ::resolve.

Serves as a wrapper for instantly derefed sub ::match.

(ns my-district.core
    (:require [mount.core :as mount]
              [district.ui.router]
              [district.ui.router.utils :as utils]))

  (-> (mount/with-args
        {:router {:routes [["/a" :route/a]
                           ["/b/:b" :route/b]]
                  :default-route :route/a}})
    (mount/start))

(utils/resolve :route/a)
;; => "/a"

(utils/resolve :route/b {:b "abc"} {:c "xyz"})
;; => "/b/abc?c=xyz"

(utils/match "/b/abc?c=xyz")
;; => [:route/b {:b "abc"} {:c "xyz"}]

district.ui.component.page

Multimethod to define pages upon. district.ui.component.router component will then route those pages according to active-page.

(ns my-district.core
  (:require
    [district.ui.component.page :refer [page]]))

(defmethod page :route/home []
  [:div "Welcome to Home Page"])

district.ui.component.router

Components that switches pages (as defined via district.ui.component.page) based on current active-page.

(ns my-district.core
  (:require
    [reagent.core :as r]
    [mount.core :as mount]
    [district.ui.router]
    [district.ui.component.page :refer [page]]
    [district.ui.component.router :refer [router]]))

  (-> (mount/with-args
        {:router {:routes [["/" :route/home]
                           ["/user" :route/user]]
                  :default-route :route/home}})
    (mount/start))

(defmethod page :route/home []
  [:div "Welcome to Home Page"])

(defmethod page :route/user []
  [:div "Welcome to User Page"])

(r/render [router] (.getElementById js/document "app"))

Development

lein deps
# To run tests and rerun on changes
lein doo chrome tests