backbone.jsunderscore.jsbackbone-routingbackbone-model

Error: a url property or function must be specified


These are my initial days of working on BackBone.js. I am actually stuck with the router part as i am getting an error in the console "Error: a url property or function must be specified". This is my scenario; I have a click function which dynamically forms a REST URL, and fetch the data from server accordingly.

Here is the click function code

function onUserClick(obj){
     var userID=$(obj).attr('id');
     window.location.href="#"+userID+"/";
     var userRouter = new UserRouter;
}

And I have the following code in the router

var userModel;
var UserRouter = Backbone.Router.extend({
    routes:{
        ":userid/":"getUsers"
    },
    getUsers:function(userid){
        var url="http://myserver.com/users/"+userid;
        userModel = new UserModel({urlRoot:url});
        var userView = new UserView({el:$(#"container")});
    }
});
var UserModel = Backbobe.Model.extend({});
var UserView = Backbone.View.extend({
    model:userModel,
    initialize:function(){
        _.templateSettings = {
            interpolate: /\{\{\=(.+?)\}\}/g,
            evaluate: /\{\{(.+?)\}\}/g
        };
        this.model.fetch();
        this.model.bind("change",this.render,this);
    },
    render:function(){
        var data=this.model.toJSON();
        var userTemplate=_.template($("#userTemplate").text());
        var htmlData=userTemplate({
            "userData":data
        });
        $(this.el).html(htmlData);
    }
});

Can someone help me to figure out the issue here? I know i have done something wrong here and seeks an expert advice on this. A woking sample for this scenario is much appreciated.


Solution

  • You're calling fetch on your model:

    var UserView = Backbone.View.extend({
        model: userModel,
        initialize: function() {
            // ...
            this.model.fetch();
    

    But you didn't give your model a url property:

    var UserModel = Backbone.Model.extend({});
    

    The fetch method talks to the server and it uses url to do so:

    url model.url()

    Returns the relative URL where the model's resource would be located on the server. If your models are located somewhere else, override this method with the correct logic. Generates URLs of the form: "/[collection.url]/[id]", falling back to "/[urlRoot]/id" if the model is not part of a collection.

    The default implementation for a Model's url looks like this:

    url: function() {
      var base = _.result(this, 'urlRoot') || _.result(this.collection, 'url') || urlError();
      if (this.isNew()) return base;
      return base + (base.charAt(base.length - 1) === '/' ? '' : '/') + encodeURIComponent(this.id);
    },
    

    You don't have a urlRoot, you don't have a collection to delegate the URL generation to, and you haven't overridden url so urlError() gets called and that's where your error message comes from.

    Your UserModel needs a RESTful url property or function so that you can fetch instances from the server. Alternatively, you could create your models from data that's already available in your client-side environment (as long as you're not planning on saving anything through Backbone of course).