7

My Code:

I am new to Backbone.js and trying to build an app with Backbone.js and PHP. When I am trying to call add in the router, I am getting error:

Uncaught TypeError: Object [object Object] has no method 'set'.

Please help me to find my mistake.

Thanks.

    // Models
    window.Users = Backbone.Model.extend({
        urlRoot:"./bb-api/users",
        defaults:{
            "id":null,
            "name":"",
            "email":"",
            "designation":""
        }
    });

    window.UsersCollection = Backbone.Collection.extend({
        model:Users,
        url:"./bb-api/users"
    });


    // Views


    window.AddUserView = Backbone.View.extend({

        template:_.template($('#new-user-tpl').html()),

        initialize:function(){
            this.model.bind("click", this.render, this);
        },

        render:function(){
            $(this.el).html(this.template(this.model.toJSON()));
            return this;
        },

        events:{
            "click .add":"saveUser"
        },

        saveUser:function(){ alert('saveUser');
            this.model.set({
                name:$("#name").val(),
                email:$("#email").val(),
                designation:$("#designation").val()
            });

            if(this.model.isNew()){
                this.model.create(this.model);
            }
            return false;
        }
    });


    // Router
    var AppRouter = Backbone.Router.extend({

        routes:{
            "":"welcome",
            "users":"list",
            "users/:id":"userDetails",
            "add":"addUser"
        },


        addUser:function(){ 
            this.addUserModel = new UsersCollection();
            this.addUserView = new AddUserView({model:this.addUserModel});
            $('#content').html(this.addUserView.render().el);
        }


    });

    var app = new AppRouter();
    Backbone.history.start();
5
  • 4
    Your passing a collection to the view and then trying to treat it as an instance of the model. It's not. It's a collection. Commented Jun 26, 2012 at 12:53
  • 1
    To clarify: the Backbone.Collection does not have a metod set. Commented Jun 26, 2012 at 13:06
  • 2
    If you're using a collection, you should new View({ collection: ... }) instead of new View({ model: ... }) and this.collection inside the view instead of this.model. That should prevent some confusion. Commented Jun 26, 2012 at 15:56
  • Hi @jakee sorry to bring up old thread but can you confirm your comment? I see it here Commented Apr 28, 2013 at 12:35
  • 1
    @Lim Backbone.Collection didn't get a set method until version 1.0.0. Nag apparently was using an earlier version. Commented Sep 27, 2014 at 4:20

2 Answers 2

1

As suggested in the comments, the problem starts here here:

this.addUserModel = new UsersCollection();
this.addUserView = new AddUserView({model:this.addUserModel});

and finishes here:

saveUser:function(){ alert('saveUser');
    this.model.set({

By passing a collection in place of a model you create confusion, and as a result later in the saveUser function you try to call a Backbone.Model method (set) on a Backbone.Collection instance.


Note: As of version 1.0.0 Backbone.Collection now has a set method. In previous versions, such as the one used by the question's author, that method was instead called update.


There are several steps you can take to clarify this code. For starters, I would rename your model and collection classes so that it's clear that the model is the singular form and the collection is the plural form:

window.Users => window.User

window.UsersCollection => window.Users

Next, I would create a new User model, instead of a Users collection, and pass that to your view:

this.addUserModel = new User();
this.addUserView = new AddUserView({model:this.addUserModel});

Finally, I'd remove these lines:

if(this.model.isNew()){
    this.model.create(this.model);
}

For one thing, the model will always be new (as you just created it before passing it in), but more importantly you don't need to call the Collection's create method because that method creates a new model, when you already have one created. Perhaps what you should add instead is :

this.model.save();

if your intent is to save the model to your server.

Since you already specified a urlRoot for the model, that should be all you need to create a new model, pass it to your view, have your view fill in its attributes based on DOM elements, and finally save that model's attributes to your server.

Sign up to request clarification or add additional context in comments.

Comments

0

I think you are facing problem with object scope. When event fired it send to event object to that function. Just try this it may work Declare global variable with the current view inside the initialize

initialize : function(){ self = this; }

then change this to self,

       saveUser:function(){ alert('saveUser');
        self.model.set({
            name:$("#name").val(),
            email:$("#email").val(),
            designation:$("#designation").val()
        });

        if(self.model.isNew()){
            self.model.create(this.model);
        }
        return false;
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.