DoneJS StealJS jQuery++ FuncUnit DocumentJS
4.3.0
5.0.0 3.13.1 2.3.35
  • About
  • Guides
  • API Docs
  • Community
  • Contributing
  • Bitovi
    • Bitovi.com
    • Blog
    • Design
    • Development
    • Training
    • Open Source
    • About
    • Contact Us
  • About
  • Guides
  • API Docs
    • Observables
      • can-bind
      • can-compute
      • can-debug
      • can-define
      • can-define/list/list
      • can-define/map/map
      • can-define-backup
      • can-define-stream
      • can-define-stream-kefir
      • can-event-queue
      • can-kefir
      • can-list
      • can-map
      • can-map-define
      • can-observation
      • can-observation-recorder
      • can-observe
      • can-simple-map
      • can-simple-observable
      • can-stream
      • can-stream-kefir
      • can-value
    • Data Modeling
      • can-connect
      • can-connect-feathers
      • can-fixture
      • can-fixture-socket
      • can-ndjson-stream
      • can-set
    • Views
      • can-component
      • can-stache
      • can-stache-bindings
      • can-stache-converters
      • can-stache-route-helpers
      • can-view-autorender
      • can-view-callbacks
      • can-view-import
      • can-view-live
      • can-view-model
      • can-view-nodelist
      • can-view-parser
      • can-view-scope
      • can-view-target
      • react-view-model
      • react-view-model/component
      • steal-stache
    • Routing
      • can-deparam
      • can-param
      • can-route
      • can-route-hash
      • can-route-mock
      • can-route-pushstate
        • static
          • root
    • JS Utilities
      • can-assign
      • can-define-lazy-value
      • can-diff
      • can-globals
      • can-join-uris
      • can-key
      • can-key-tree
      • can-make-map
      • can-parse-uri
      • can-queues
      • can-string
      • can-string-to-any
      • can-util
      • can-zone
      • can-zone-storage
    • DOM Utilities
      • can-ajax
      • can-attribute-encoder
      • can-child-nodes
      • can-control
      • can-dom-data
      • can-dom-events
      • can-dom-mutate
      • can-event-dom-enter
      • can-event-dom-radiochange
      • can-fragment
    • Data Validation
      • can-define-validate-validatejs
      • can-validate
      • can-validate-interface
      • can-validate-legacy
      • can-validate-validatejs
    • Typed Data
      • can-cid
      • can-construct
      • can-construct-super
      • can-data-types
      • can-namespace
      • can-reflect
      • can-reflect-dependencies
      • can-reflect-promise
      • can-types
    • Polyfills
      • can-symbol
      • can-vdom
    • Core
    • Infrastructure
      • can-global
      • can-test-helpers
    • Ecosystem
    • Legacy
  • Community
  • Contributing
  • GitHub
  • Twitter
  • Chat
  • Forum
  • News
Bitovi

can-route-pushstate

  • npm package badge
  • Star
  • Edit on GitHub

Changes can-route to use pushstate to change the window's pathname instead of the hash.

import route from "can-route-pushstate";

route( "{page}", { page: "home" } );
route.start();

route.attr( "page", "user" );

location.pathname; // -> "/user"

Object

Options

  • The {Object}:

    pushstate object comprises several properties that configure the behavior of can-route to work with history.pushstate.

Use

can-route-pushstate uses the same API as can-route. To start using can-route-pushstate all you need is to import can-route-pushstate, it will set itself as default binding on can-route.

You can check current binding by inspecting route.currentBinding; the default value is "hashchange".

Creating and changing routes

To create routes use route(url, defaults) like:

route( "{page}", { page: "homepage" } );
route( "contacts/{username}" );
route( "books/{genre}/{author}" );

route.start(); // Initializes can-route

Do not forget to initialize can-route after creating all routes, do it by calling route.start().

List of defined routes is contained in route.routes, you can examine current route state by calling:

route.attr(); //-> {page: "homepage", route: "{page}"}

After creating routes and initializing can-route you can update current route by calling route.attr(attr, newVal):

route.attr( "page", "about" );
route.attr(); //-> {page: "about", route: "{page}"}

// without cleaning current route state
route.attr( "username", "veljko" );
route.attr(); //-> {page: "about", route: "{page}", username: 'veljko'}

// with cleaning current can-route state
route.attr( { username: "veljko" }, true );
route.attr(); //-> {username: "veljko", route: "contacts/{username}"}

To update multiple attributes at once pass hash of attributes to route.attr(hashOfAttrs, true). Pass true as second argument to clean up current state.

route.attr( { genre: "sf", author: "adams" }, true );
route.attr(); //-> {genre: "sf", author: "adams", route: "books/{genre}/{author}"}

window.location acts as expected:

window.location.pathname; //-> "/books/sf/adams"
window.location.hash; //-> "", hash remains unchanged

To generate urls use route.url({attrs}):

route.url( { username: "justinbmeyer" } ); //-> '/contacts/justinbmeyer'

Listening changes on matched route

As can-route contains a map that represents window.location.pathname, you can bind on it.

To bind to specific attributes on can-route:

route.bind( "username", function( ev, newVal, oldVal ) {

    //-> ev:     {EventObject}
    //-> newVal: 'nikica'
    //-> oldVal: 'veljko'
} );

route.attr( { username: nikica }, true );

Using different pathname root

can-route-pushstate has one additional property, route.bindings.pushstate.root, which specifies the part of that pathname that should not change. For example, if we only want to have pathnames within http://example.com/contacts/, we can specify a root like:

route.bindings.pushstate.root = "/contacts/";
route( "{page}" );
route.url( { page: "list" } ); //-> "/contacts/list"
route.url( { foo: "bar" } );   //-> "/contacts/?foo=bar"

Now, all routes will start with "/contacts/", the default route.bindings.pushstate.root value is "/".

Updating the current route

can-route-pushstate also allows changes to the current route state without creating a new history entry. This behavior can be controlled using the replaceStateOn, replaceStateOff, and replaceStateOnce methods.

Enable the behavior by calling replaceStateOn with specified route property keys like:

route.replaceStateOn( "page", "action" );
route.attr( "page", "dashboard" ); // Route changes, no new history record

To return the attr call back to normal the pushstate behavior, call replaceStateOff with the specified route property keys like:

route.replaceStateOff( "action" );
route.attr( "action", "remove" ); // Route changes, new history record is created

The behavior can be configured to occur only once for a specific property using replaceStateOnce like:

route.replaceStateOnce( "page" );
route.attr( "page", "dashboard" ); // No new history record
route.attr( "page", "search" ); // New history record is created

Planning route structure

Complications can arise if your route structure mimics the folder structure inside your app's public directory. For example, if you have a folder structure like the one in this url for your admin app...

/admin/users/list.js

... using a route of /admin/users on the same page that uses the list.js file will require the use of a trailing slash on all routes and links. The browser already learned that '/admin/users' is folder. Because folders were originally denoted by a trailing slash in a url, the browser will correct the url to be '/admin/users/'. While it is possible to add the trailing slash in routes and listen for them, any link to the page that omits the trailing slash will not trigger the route handler.

CanJS is part of DoneJS. Created and maintained by the core DoneJS team and Bitovi. Currently 4.3.0.

On this page

Get help

  • Chat with us
  • File an issue
  • Ask questions
  • Read latest news