12

I have a basic application using Backbone.js that is not making PUT calls (updating model). From the front-end, I calling a models save function doesn't make a PUT call; however, if I replace it with destroy, it does make a DELETE call to the back-end. Anyone have any idea what might be the issue? The function that is not firing a PUT request is the saveTask function.

App.Views.Task = Backbone.View.extend({
    template: _.template("<label>ID:</label><input type='text' id='taskId' name='id' value='<%= _id %>' disabled /><br><label>Title:</label><input type='text' id='title' name='title' value='<%= title %>' required/><br><label>Content:</label><input type='text' id='content' name='content' value='<%= content %>'/><br><button class='save'>Save</button>"),
    events: {
        "change input":"change",
        "click .save":"saveTask"
    },
    render: function(eventName){
        $(this.el).html(this.template(this.model.toJSON()));
        //console.log(this.generateTemplate());
        return this;
    },
    change: function(event){
        var target = event.target;
        console.log('changing ' + target.id + ' from: ' + target.defaultValue + ' to: ' + target.value);
        change[target.name] = target.value;
        this.model.set(change);*/
    },
    saveTask: function(){
        this.model.set({
            title:$("#title").val(),
            content:$("#content").val()
        });
        if(this.model.isNew()){
            App.taskList.create(this.model);
        } else {
            this.model.save({});
        }
    }
});
Theo Alvarez
  • 123
  • 1
  • 1
  • 5
  • What version of Backbone are you using? I had some issues when updating a model with version 0.9.9. It might be a silent error during the save or a bug with your version of backbone. – mor Jun 20 '13 at 22:55

4 Answers4

20

If your model is new, then at the time you save it it will fire a post method. If your model however is not new and you are updating it, it will fire a PUT.

if this is not working for you it may be because your model does not have an id property, in case you are using an id with a different name, for example taskID, then in your model you have to set the idAttribute to taskID so backbone uses this property as the Id and everything will be normal.

like this:

 var Task= Backbone.Model.extend({
   idAttribute: "taskId"
 });

here is the link to the documentation on Idattibute http://backbonejs.org/#Model-idAttribute

also another problem could be the {} in your save call try just

 this.model.save(); 

instead of

 this.model.save({});
shaedrich
  • 5,457
  • 3
  • 26
  • 42
Rayweb_on
  • 3,727
  • 20
  • 24
  • Thanks for the response. My model does have an ID property, and I has set the `idAttribute` - to make sure, I checked the model's id (`this.model.id`) as I try to save. It still does not fire a PUT though - and `model.destroy()` works fine. Am I missing anything else? – Theo Alvarez Jun 20 '13 at 21:08
  • why do you have the {} inside the save call? i think it should be just model.save(); with no empty object literal as parameter. – Rayweb_on Jun 20 '13 at 21:13
  • Thanks - it's a typo (previously tried to use the success callback), but it doesn't seem to be related (no difference). The model is changing correctly (attributes are updated), but not saving to the server. – Theo Alvarez Jun 20 '13 at 21:47
  • is then trowing an error? in the network tab of chrome, is any kind of network activity at the time you hit save? – Rayweb_on Jun 20 '13 at 23:36
  • Thank you - I chased down the problem based on your lead. Was an error in the API back end (there was network activity that never returned) – Theo Alvarez Jun 22 '13 at 05:24
  • Great! I'm glad I was able to help. – Rayweb_on Jun 22 '13 at 17:13
2

I believe model is always expecting options parameter and also probably the callbacks

this.model.save(null, {
    success: function (model, response) {

        //
    },
    error: function () {
        //
    }
});

If you look at Backbone src, you will notice that too...

======

// Set a hash of model attributes, and sync the model to the server.
// If the server returns an attributes hash that differs, the model's
// state will be `set` again.
save: function (key, val, options) {
    var attrs, method, xhr, attributes = this.attributes;

    // Handle both `"key", value` and `{key: value}` -style arguments.
    if (key == null || typeof key === 'object') {
        attrs = key;
        options = val;
    } else {
        (attrs = {})[key] = val;
    }

    options = _.extend({
        validate: true
    }, options);

    // If we're not waiting and attributes exist, save acts as
    // `set(attr).save(null, opts)` with validation. Otherwise, check if
    // the model will be valid when the attributes, if any, are set.
    if (attrs && !options.wait) {
        if (!this.set(attrs, options)) return false;
    } else {
        if (!this._validate(attrs, options)) return false;
    }

    // Set temporary attributes if `{wait: true}`.
    if (attrs && options.wait) {
        this.attributes = _.extend({}, attributes, attrs);
    }

    // After a successful server-side save, the client is (optionally)
    // updated with the server-side state.
    if (options.parse === void 0) options.parse = true;
    var model = this;
    var success = options.success;
    options.success = function (resp) {
        // Ensure attributes are restored during synchronous saves.
        model.attributes = attributes;
        var serverAttrs = model.parse(resp, options);
        if (options.wait) serverAttrs = _.extend(attrs || {}, serverAttrs);
        if (_.isObject(serverAttrs) && !model.set(serverAttrs, options)) {
            return false;
        }
        if (success) success(model, resp, options);
        model.trigger('sync', model, resp, options);
    };
    wrapError(this, options);

    method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update');
    if (method === 'patch') options.attrs = attrs;
    xhr = this.sync(method, this, options);

    // Restore attributes.
    if (attrs && options.wait) this.attributes = attributes;

    return xhr;
},
addisu
  • 634
  • 1
  • 4
  • 12
2

In my case it fails due to validations.As i save the model it validates all the attributes of the model and the collection which i am using for listing interface doesn't required all the attributes of the model.

I was facing the same issues and search in Google and found your question and read the solution and comments.Than i realize that in updated backbone specifications it is mentioned that when model.save() executes before model requests,it first call validate and if validate succeeds than it will go ahead other wise fails, and that is the reason why it doesn't showing any network request in chrome debugger network tab.

I have write the solution for the case which i am facing,other might be facing different issues.

Ahesanali Suthar
  • 341
  • 3
  • 23
0

Backbone's sync function is what I wound up using. You have to pass in 'update' as the first parameter (the 'method' parameter).

Stubbs
  • 323
  • 1
  • 4
  • 14
  • It'd be nice to know what the down vote is for. A lot more constructive for me and this site as well :) – Stubbs Nov 01 '16 at 21:52