Halt execution of routes using backbone.js

Is it feasible to halt route execution within backbone.js solely using the router?

I understand there is a callback function for each route where I could verify if routing is permitted, but I am unsure how to prevent execution based on a property (such as canNavigate) on my viewmodel.

Additionally, I would like this functionality to apply to URLs that are not explicitly specified as routes (sammy.js lacks this capability, can backbone accomplish this?). For instance:

Upon opening the route #/contact, the active method in the 'contact' viewmodel should be invoked. When transitioning away from #/contact to any other URL like #/page1, /page2, or google.com, I want the canNavigate method in the contact viewmodel to be triggered. If this method returns false, the routing to those URLs should be blocked and an error message displayed (I am only interested in the backbone.js code implementation).

Is it achievable with backbone.js? If not, what other framework (besides sammy.js which we have already tried) could possibly achieve this?

Answer ā„–1

If you want to implement custom routing in any framework, it can be done by creating a Router extension. This process is usually quicker than seeking help online. While I'm not certain if Backbone supports this feature out of the box, I will investigate the code to confirm.

The key method for achieving custom routes is as follows:

route: function(route, name, callback) {
  if (!_.isRegExp(route)) route = this._routeToRegExp(route);
  if (!callback) callback = this[name];
  Backbone.history.route(route, _.bind(function(fragment) {
    var args = this._extractParameters(route, fragment);
    callback && callback.apply(this, args);
    this.trigger.apply(this, ['route:' + name].concat(args));
    Backbone.history.trigger('route', this, name, args);
  }, this));
  return this;
},

Essentially, this method simply executes the callback function without blocking anything else.

You have the freedom to extend this functionality, for example, like so:

var RouteError(message) {
    this.name = "RouteError";
    this.message = (message || "");
}
RouteError.prototype = Error.prototype;


var MyRouter = function (){
    Backbone.Router.apply(this, arguments);
};
MyRouter.prototype = Object.create(Backbone.Router.prototype);
MyRouter.prototype.constructor = MyRouter;
_.extend(MyRouter.prototype, {
    route: function(route, name, callback) {
      if (!_.isRegExp(route)) route = this._routeToRegExp(route);
      if (!callback) callback = this[name];
      Backbone.history.route(route, _.bind(function(fragment) {
        var args = this._extractParameters(route, fragment);
        try {
            callback && callback.apply(this, args);
        }
        catch(e)
        {
            if (e instanceof RouteError)
                return this;
            else
                throw e;
        }
        this.trigger.apply(this, ['route:' + name].concat(args));
        Backbone.history.trigger('route', this, name, args);
      }, this));
      return this;
    },
});

Alternatively, you could modify the behavior like this:

var loadUrl = Backbone.History.prototype.loadUrl;
Backbone.History.prototype.loadUrl = function (fragmentOverride){
    try {
        loadUrl.apply(this, arguments);
    }
    catch (e){
        if (e instanceof RouteError)
            return ;
        else
            throw e;
    }

};

(Please note that these examples have not been tested...)

Based on my understanding, it seems that native support for this feature may be lacking in Backbone...

Answer ā„–2

When working with Backbone, I discovered that the best way to check things before or after routing is by extending Router.route. It may not be the cleanest solution as it involves copying code from the source and making edits, but it's the only method I've found so far. Below is the default Backbone code (version 1.0.0) along with the custom code you'll need:

  Backbone.Router.prototype.route = function(route, name, callback) {
    if (!_.isRegExp(route)) route = this._routeToRegExp(route);
    if (_.isFunction(name)) {
      callback = name;
      name = '';
    }
    if (!callback) callback = this[name];
    
    // Custom code starts here
    callback = _.wrap(callback, _.bind(function(cb) {
      console.log('before');
      _.bind(cb, this)();
      console.log('after');
    }, this));
    // End of custom code
    
    var router = this;
    Backbone.history.route(route, function(fragment) {
      var args = router._extractParameters(route, fragment);
      callback && callback.apply(router, args);
      router.trigger.apply(router, ['route:' + name].concat(args));
      router.trigger('route', name, args);
      Backbone.history.trigger('route', router, name, args);
    });
    return this;
  };

Pay attention to _.wrap and _.bind to ensure that this behaves as expected when using the router. This prevents a "this is undefined" error.

Now, you have the ability to perform checks before and after your routes are executed. Within the affected router, you can load your view and carry out any necessary actions.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

"Utilize jQuery to superimpose an image on top of

I'm attempting to create a feature where clicking on an image will reveal text underneath, similar to how retailmenot.com displays coupon codes. In addition, when the image is clicked, users should be directed to an external URL. Here is an example o ...

AngularJs JSON endpoint modifier

I've been working on a simple weather app in Angular for practice, but I've hit a roadblock. Here's the Angular JSON feed I'm using: app.factory('forecast', ['$http', function($http) { return $http.get('http: ...

Can the FB status update popup be displayed when clicked?

I've implemented a code on my website that allows users to update their Facebook status directly from the page: <head> <title>My Awesome Site</title> </head> <body> <div id="fb-root"></div> <script s ...

javascript utilize bluebird promise to asynchronously retrieve the first file from a given list

I am currently working on implementing promises in JavaScript to retrieve the first available file from a list of paths (for example, ["c:\\temp\\test1.json", "c:\\temp\\test2.json"]). The goal is to identify and ret ...

What causes the generation of an outdated object when utilizing the let and new keywords to create a new object within a service function?

Hey there, looking for a basic auth authentication service in angular2? Here's the issue I'm facing: When a user logs in for the first time, everything works smoothly. However, if they try to log in with a different account for the second time, ...

Troubleshooting the issue of React forms hook not functioning properly with Material UI Select input

How the Textfield below should load: https://i.sstatic.net/29Sz4.png How it actually loads: https://i.sstatic.net/TdPYM.png My Select component, created using Material UI and React form hook, is not loading the default value as expected. The component ...

Can you explain how to extract information from an API response using res.send?

Utilizing the MEAN stack in JavaScript for my single page application has been seamless. A crucial component of my architecture involves an Angular factory that communicates with my API. app.factory('authorizing', function($resource){ retur ...

Unable to render data in Chart JS using PHP JSON

Hello, Iā€™m currently working on creating a dynamic line chart using Chartjs. The data is being pulled from an SQL database using PHP in JSON format. Although the data is successfully retrieved, the chart appears blank. Any assistance would be greatly app ...

Having trouble updating state with useEffect in a React functional component

Currently, I am dealing with a React functional component that is calling an API to fetch data. The response from the API call is confirmed to be received successfully. My aim is to store this data in an array within the component's state so that it c ...

The appearance of the logout button may differ depending on the web browser being used

I have implemented a straightforward logout button using the following code: <li><a href="http://localhost:8666/web1/profile/mainpage/logout.php" onclick="return confirm('Are you sure to logout?');">Log Out</a>&l ...

Which Angular component, directive, or pipe would be best suited for creating dynamic HTML content similar to this?

(I am transitioning from React to Angular, so please bear with me if my question has a hint of React influence.) I am in need of developing an Angular component that can accept a string along with a list of terms within that string for displaying tooltips ...

The appearance of the check box remains stagnant visually

Having trouble with dynamically changing the state of a checkbox based on a database value. Even though the value changes after a button click, the visual state of the checkbox remains the same. Here is the link to the JSFiddle for testing: http://jsfiddle ...

Issues with React Material UI Dialog Displaying Incorrect Information

As I experiment with React Material UI dialog boxes, I've encountered an issue that has me puzzled. I have an object 'a', and when I click on a button in a list, it should display the respective ID number. However, instead of showing the cor ...

Having difficulty making Skrollr compatible with BootStrap 3 single page wonder

I am completely new to JavaScript, which is why I decided to use Skrollr. However, I have been facing some challenges in getting Skrollr to work properly on my webpage. I added the following code at the end of my page: <script type="text/javascript" sr ...

Next JS restricts XLSX to return only 100 objects as an array of arrays

I've developed a file upload system that reads Excel files and uploads data to a database (using Mongoose). After implementing the code, I noticed that when I use console.log(sheetData), it returns an array of arrays with objects inside. Each internal ...

Unable to display image on HTML page in Sails JS

In my current project, I am utilizing Sails Js and Mongo DB for development. When a user uploads an image and content for a blog post, I store it in the images folder and save the file destination along with the content to MongoDB. My goal is to display bo ...

Finding specific data in sessionStorage using an ID or key

I have stored data in sessionStorage and this is an example of how I save the data: $.ajax({ type: 'POST', url: 'Components/Functions.cfc?method='+cfMethod, data: formData, dataType: 'json' }).done(function(ob ...

Not adhering to directive scope when transclusion is used, despite explicit instructions to do so

Trying to use a transcluding directive within another controller, but the inner scope isn't being redefined as expected. Despite trying different methods, I can't seem to figure out what's going wrong. The simplified code looks like this: ...

Problem with deleting or substituting symbols and character codes within a String

I am attempting to send an object called dataO from Node.js/Express/EJS to the client side. On the Node.js script side: var dataO = {"first":[20000, 14000, 12000, 15000, 18000, 19000, 22000], "second":[12000, 11000, 18000, 12000, 19000, 14000, 26000]}; var ...

"Pushing elements into an array does not function properly within a promise

I'm having trouble with my code - the push method isn't working and it's not returning anything. import {nearbyUsers, getLatitude, getLongitude} from './helper' const users = [] nearbyUsers(session, getLatitude(), getLongitude()).t ...