orad
orad

Reputation: 16074

Backbone routing doesn't work when converted to TypeScript

I'm trying to convert a basic Backbone.js router declaration to TypeScript.

var AppRouter = Backbone.Router.extend({
    routes: {
        "*actions": "defaultRoute"
    },

    defaultRoute: function () {
        document.write("Default Route Invoked");
    }
});

var app_router = new AppRouter();

Backbone.history.start();

My converted code is the following which doesn't work:

class AppRouter extends Backbone.Router {
    routes = {
        "*actions": "defaultRoute"
    }

    defaultRoute() {
        document.write("Default Route Invoked");
    }
}

var app_router = new AppRouter();

Backbone.history.start();

I get no compile time or runtime errors but the code does not function. Why?

Upvotes: 2

Views: 1538

Answers (4)

Martins Balodis
Martins Balodis

Reputation: 2068

The accepted answer doesn't seem to work with typescript 3.x . The super() method should be called before using this. Reordering code won't work because backbone is initializing routes within the super() method. Here is a version where the route configuration is directly passed to super().

class AppRouter extends Backbone.Router {

    constructor() {

        super({
            routes: {
                "*actions": "defaultRoute"
            }
        });
    }
}

Upvotes: 0

orad
orad

Reputation: 16074

Add all initialized fields in the constructor and make a call to super at the end:

class AppRouter extends Backbone.Router {

    routes: any;
    constructor(options?: Backbone.RouterOptions) {

        this.routes = {
            "*actions": "defaultRoute"
        }

        super(options);
    }

    initialize() {
        // can put more init code here to run after constructor
    }

    defaultRoute() {
        document.write("Default Route Invoked");
    }
}

var app_router = new AppRouter();

Backbone.history.start();

Upvotes: 2

Tau Sand
Tau Sand

Reputation: 23

As Steve Fenton mentioned it's because Typescripts extend does not work in the same way as underscore / backones extend method.

The main problem is that the router calls _bindRoutes() before your routes field has been set in the "sub class" in type scripts hierachy.

A call to Backbone.Router.apply(this, arguments) in the constructor of your ts class as described by orad, ensures that this call will be made after the routes field has been set.

A manual call to this function will do the trick as well.

and just a FYI: call delegateEvents(this.events) in the constructor of your view classes if you want the dom events from your element to get triggered

Upvotes: 2

Fenton
Fenton

Reputation: 251072

I've had a look at Backbone.Router.extends and it isn't a basic prototype extension - so you can't just switch from Backbone.Router.extends to a TypeScript class extension.

I would change your TypeScript file to look more like your original JavaScript - you'll still get the benefit of intellisense and type checking - you just aren't using a class:

var AppRouter = Backbone.Router.extend({
    routes: {
        "*actions": "defaultRoute"
    },

    defaultRoute: function () {
        document.write("Default Route Invoked");
    }
});

var app_router = new AppRouter();

Backbone.history.start();

Upvotes: 2

Related Questions