9
votes

I have been trying out backbone.js and have been stymied when I create a new model object then call model.save(). I am expecting the backbone.js default behavior to update the model object with the id from the database but it is not. Is this not supposed to happen? I have verified that I am getting a post with the attributes in json format. My server saves the json to a table and then returns the json with a new id field to backbone.js. Is this correct? Should my server return the entire new object or just the id or what?

//contents of the POST from backbone.js
  { "text":"this is a test" }

//reply from my server
  { id:"15", text:"this is a test"  }

My sample code is below

var SQLRow = Backbone.Model.extend({
 table:"",
 urlRoot:'db',
 url:function () {
    return "/" + this.urlRoot + "?table=" + this.table + 
                 "&id=" + this.attributes.id;
   }
});

var Xtra = SQLRow.extend ({
   table:'Xtra'
});

var row = new Xtra({
  text: "this is a test" 
});

alert(row.url());
row.save()
alert("row:" + row.get("id"));
4
What does the response look like that's returned from the save call?kinakuta

4 Answers

6
votes

Tough to tell from your post. Two ideas :

1) the response from the server isn't successful What does your save call return ?

2) Your "id" attribute is named something other than ID. To account for the different name add the following to your model :

   idAttribute  : "MyModelsID",

EDIT

You're likely facing a timing issue, where the alert fires before the ID has returned. Instead of your last two lines try this :

row.save( null, 
              { 
                 success : function(model, response) { alert(model.get('id'); } 
               }
         );

ALTERNATIVE

As @mu_is_too_short mentioned, another way is to listen for the change even on the model and respond to the event. (i was just trying to keep the answer as close to your code as possible). But something like the following pseudo code should get you started...

var myView = Backbone.View.extend({
           ....
           initialize : function () {
                this.collection.bind('change',  this.SOME_LISTENING_FUNC    );

             }
  });

OR, if you're in a collection/view-less world something like this creates a listenr ...

row.on('change',  function() {  /* do stuff */ }, this);               
1
votes

This answer is based on one comment of Cjolly in the answer above.

It is essential for making the Backbone.Model.save([attributes],[options]) successful in assiging the model with the newly generated model's id from the server, that the server returns the model's id in a JSON string like this { "id" : <the id> }. (note it is "id" and not id).

In essence backbone rightly expects a JSON string and in contrast to how objects may be defined in Javascript without quoted keys, JSON requires the object keys to be quoted (see JSON Spec - does the key have to be surrounded with quotes?)

Since according to Cjolly's comment this has been the essential problem, I want to hightlight this solution in an second answer. Partially because I was hit by the very same problem and only by reading througth the comments I was able to receive the insight.

0
votes

I've faced the same issue and what I've found is that my validate function of the saved model actually invalidates the model returned from the back end. That's why my fields were not updated properly.

0
votes

Maybe its a little outtimed, but today I had the same missing id. It turns out, that the server just sends a Header 'Location' with a redirect containing the new id, but dosen't return the persisted object. Adding the object to the response was the solution. It seems, that not returning the object is standard behavier with Roo(Spring) generated Json-Controllers.