jComponent / Helpers / Navigation for SPA
Updated: 26. November 2019
Author: Peter Širka

Navigation for Single Page Applications

Professional Support Chat with contributors

Navigation uses jRouting library, this library is designed for creating Single Page Applications. jComponent navigation uses two aliases to navigation:

Quick navigation:

Properties

// +v16 Enables hashtags instead of HTML 5 History API
// default: false
// returns {Boolean}
NAV.hashtags;

// Contains the current URL address
// IMPORTANT: a path can be used in jComponent
// returns {String}
NAV.url;

// +v16 Is back button enabled?
// returns a count of page numbers for "back" button
// IMPORTANT: a path can be used in jComponent
// returns {Number}
NAV.isback;

// +v16 Is forward button enabled?
// returns a count of page numbers for "forward" button
// IMPORTANT: a path can be used in jComponent
// returns {Number}
NAV.isforward;

// +v17 Contains "params" data parsed according to the URL
// IMPORTANT: a path can be used in jComponent
// returns {Object}
NAV.params;

// +v17 Contains a repository data for each URL
// IMPORTANT: a path can be used in jComponent
// returns {Object}
NAV.repository;

// +v17 Contains parsed query arguments according to the URL
// IMPORTANT: a path can be used in jComponent
// returns {Object}
NAV.query;

Methods

MIDDLEWARE()

Method registers a new middleware for routing. Middleware are async methods which can stop route execution while all middlewares aren't done. Look on example with Middleware.

MIDDLEWARE(name, fn);
// @name {String} A middleware name
// @fn {Function(next)} Executor
// returns {NAV}

MIDDLEWARE('delay', function(next, options, roles) {
    // @next {Function} "next(false)" or "next(Error") won't be continue in processing
    // @options {Object} custom options defined in a route
    // @roles {String Array} roles defined in a route
    setTimeout(next, 1000);
});

+v15 supports middleware execution outside of routes:

MIDDLEWARE(['delay', 'users'], function() {
    // all middlewares are done
});

NAV.autosave()

+v16 This method performs saving of history into the localStorage. It can be executed onetime when the application is starting.

NAV.autosave();

NAV.back()

Method performs browser back operation.

NAV.back();
// returns {NAV}

NAV.clientside()

  1. If the user click on the link then the method performs internal REDIRECT() - browser doesn't perform a classic redirect to server-side. This method will watch all links and the links can be created dynamically.
NAV.clientside(selector);
// @selector {String} jQuery selector
// returns {NAV}

NAV.clientside('a.routing');

NAV.forward()

+v16 Method performs browser forward operation.

NAV.forward();
// returns {NAV}

NAV.load([expiration])

+v16 This method loads a history from the localStorage. It can be executed onetime when the application is starting.

NAV.load([expiration]);
// @expiration {String} optional, can contain an expiration for the history

NAV.load('1 hour'); // loads a history if the history wasn't saved more than 1 hour
// or
NAV.load(); // loads a history

NAV.refresh()

Method performs refresh.

NAV.refresh();
// returns {NAV}

NAV.remove()

Method removes registered routing.

NAV.remove(url);
// @url {String}
// returns {NAV}

NAV.remove('/');

NAV.save()

+v16 This method saves a history into the localStorage. NAV.autosave() executes this method automatically if the history was modified.

NAV.save();

REDIRECT()

Method performs redirect without calling backend.

REDIRECT(url, [model]);
// @url {String} relative URL address
// @model {Object} custom model for this route

REDIRECT('/users/');

ROUTE()

Method registers a new route. More info in Routing section bellow.

ROUTE(url, fn, [middleware], [init]);
// @url {String} relative URL address
// @fn {Function} executor
// @middleware {String Array} optional, can contain middleware + roles + options
// @init {Function} optional, init function is executed only the one time

ROUTE('/', function() {
    // action
}, ['middlewareA', 'middlewareB', '@role1', '@role2']);

Events

Global navigation events.

ON('location', function(url) {
    // URL address has been changed
});

ON('404', function(err) {
    // Route not found.
});

ON('500', function(err) {
    // Internal client-side error
});

Routing

Routing can be defined everywhere, but I recommend to create it in some client-side file like routes.js for clarity.

ROUTE('/', function() {
    // this action is executed if the URL will be "/"
});

ROUTE('/users/', function() {
    // this action is executed if the URL will be "/users/"
});

ROUTE('/products/{category}/', function(category) {
    // this action is executed if the URL will be "/products/SOMETHING/"
    console.log(category);
});

Middleware

Middleware can affect routing's action before is executed. So you can perform authorization or another operations in middleware, for example:

MIDDLEWARE('authorize', function(next, options, roles) {

    if (window.user)
        return next();

    // ...
    // sign-in
    window.user = user;
    next();
    
});

Custom options + roles in middleware:

ROUTE('/', function() {
    
    // some action
    
}, ['middleware', { name: 'Custom options' }, '@admin']);

MIDDLEWARE('middleware', function(next, options, roles) {

    console.log(options);
    // Output: { name: 'Custom options' }

    console.log(roles);
    // Output: admin

    next();
});

Custom errors in middleware:

MIDDLEWARE('error', function(next, options, roles) {

    if (someError) {    
        next(false); // or next(ErrorInstance)
        REDIRECT('/fallback/'); // or do something
        return;
    }

    next();
    
});

Good to know

How to read a value from URL address?

var query = READPARAMS();
// or
// var query = READPARAMS('q=Peter&age=30');

// ?q=Peter
console.log(query.q);
// Output: Peter

// ?age=30
console.log(query.age);
// Output: 30