• Stars
    star
    250
  • Rank 162,397 (Top 4 %)
  • Language
    Clojure
  • License
    Eclipse Public Li...
  • Created about 9 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

ClojureScript navigation for single-page applications, made simple.

Accountant

Accountant is a ClojureScript library to make navigation in single-page applications simple.

By default, clicking a link in a ClojureScript application that isn't a simple URL fragment will trigger a full page reload. This defeats the purpose of using such elegant frameworks as Om, Reagent, et al.

With Accountant, links that correspond to defined routes will trigger dispatches to those routes and update the browser's path, but won't reload the page.

Accountant also lets you navigate the app to a new URL directly, rather than through <a> tags.

Be aware that Accountant relies on the browser's HTML5 history, so older browsers will be left behind.

Installation

Just add the following to your project.clj:

:dependencies [venantius/accountant "0.2.5"]

Usage

All you have to do to get Accountant working is the following:

(ns your-app-ns
  (:require [accountant.core :as accountant]))

(accountant/configure-navigation!
  {:nav-handler   (fn [path] ...)
   :path-exists?  (fn [path] ...)})

The :nav-handler value is a fn of one argument, the path we're about to navigate to. You'll want to make whatever side-effect you need to render the page here. If you're using secretary, it'd look something like:

(fn [path]
  (secretary/dispatch! path))

If you're using bidi + just rendering via react, that might look like:

(fn [path]
  (om/update! app [:path] path))

The :path-exists? value is a fn of one argument, the path that we're about to navigate to. The fn should return truthy if the path is handled by your SPA, because accountant will call event.preventDefault() to prevent the browser from doing a full page request.

Using secretary, :path-exists? should have a value like:

(fn [path]
  (secretary/locate-route path))

Using bidi, it would look like:

(fn [path]
  (boolean (bidi/match-route app-routes path)))

By default, clicking a link to the currently active route will not trigger the navigation handler. You can disable this behavior and always trigger the navigation handler by setting reload-same-path? to true during configuration.

(accountant/configure-navigation! {:nav-handler (fn [path] ...)
                                   :path-exists? (fn [path] ...)
                                   :reload-same-path? true})

You can also use Accountant to set the current path in the browser, e.g.

(accountant/navigate! "/foo/bar/baz")

If you want to dispatch the current path, just add the following:

(dispatch-current!)

Note that both navigate! and dispatch-current! can only be used after calling configure-navigation!

To cleanup the resources allocated by configure-navigation!, use unconfigure-navigation!. This is useful in cases where you create a component that manages configuring navigation, and would like to be able to easily start/stop it.

(accountant/unconfigure-navigation!)

Caveat: UI Frameworks

Sometimes links may be used nested within UI components, especially when using third-party wrappers, like react-bootstrap etc. These links may have an empty href attribute or a value like #. Two things might happen: Either, if a route is defined for the root path (i.e. '/' or '/#'), accountant will suppress the browser navigation and dispatch via secretary or the browser will reload the page.

To prevent this accountant looks for an attribute data-trigger on every link. The presence of this attribute signals that this link is a means to trigger a callback, not a navigation. If data-trigger is defined on a link it gets completely ignored, just like a button.

Example: When using a DropdownButton with MenuItems each item will contain an <a href="#"...> element. Since this element can't be replaced, we can at least add arbitrary attributes to it:

(let [dropdown-button (reagent/adapt-react-class js/ReactBootstrap.DropdownButton)
      menuitem (reagent/adapt-react-class js/ReactBootstrap.MenuItem)]
  [dropdown-button {:id "foo" :title "..." :onSelect (fn [idx]...)}
    [menuitem {:id "1"
               :data-trigger true
               :eventKey "1"}]

License

Copyright © 2017 W. David Jarvis

Distributed under the Eclipse Public License, the same as Clojure.

More Repositories

1

ultra

A Leiningen plugin for a superior development environment
Clojure
1,245
star
2

pyro

Light up your Clojure stacktraces
Clojure
318
star
3

yagni

A Leiningen plugin for finding dead code
Clojure
219
star
4

glojure

The Glojure programming language
Go
172
star
5

vim-cljfmt

A Vim plugin for cljfmt, the Clojure formatting tool.
Vim Script
152
star
6

glow

Syntax highlighting for Clojure source code.
Clojure
101
star
7

vim-eastwood

A Vim plugin for Clojure's Eastwood linter
Vim Script
84
star
8

dotfiles

It's creepy that you want these
Shell
18
star
9

maze

Mazes for Programmers
Go
7
star
10

photon

Experiments in realtime web framework design. Like Meteor, but for Clojure(Script)
Clojure
7
star
11

droplet

Droplet is a Python library for sampling, sketching, and summarizing data from massive data streams.
Python
6
star
12

school

C
2
star
13

takehome

Various puzzles, homework assignments, and interview questions
Python
2
star
14

rethink

A Clojure driver for RethinkDB.
Clojure
1
star
15

yagni-test

Dummy app for testing Yagni
Clojure
1
star
16

spindle

Playing with Node.js and express. Don't take this seriously.
JavaScript
1
star
17

demo

A demo application that shows repeated 404s for a valid worker endpoint using Google App Engine push queues
Go
1
star
18

babel

Chat bots for yo' chat ops.
Clojure
1
star
19

etrade-statement-scraper

A Python script for scraping E*Trade monthly statements for data
Python
1
star
20

shrike

Hosted Code Quality for Clojure -- an abandoned CodeClimate competitor.
CSS
1
star
21

orcs-in-space

Orcs in space!!!
Haskell
1
star
22

darg

Kill the status meeting -- an abandoned IDoneThis competitor.
CSS
1
star