Search code examples
javascriptbackbone.jssynchronizationbackgrid

Backbone (sync) update event


Is the second time i'm asking this question, in the first time the text was confused for understand, sorry for this. Here are the same question improved and best explained.

I have a PageableCollection, the data is loaded without problem! The lines of the table (i'm using backgrid, extension for backbone) are editable!! BUT after edit and press enter button nothing happens! The server are not called, i wait for some call ajax for server but it not happen.

I find the way to override the sync, but i realy don't know what i want to do for make a call after edit and say "okay" or "error updating".

code bellow:

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

var PageableTerritories = Backbone.PageableCollection.extend({
    model: Territory,
    url: "linhas/results",
    state: {
        pageSize: 9
    },
    mode: "client",
    sync: function (method, model, options){
        return Backbone.sync(method, model, options);
    }
});


var pageableTerritories = new PageableTerritories(),
    initialTerritories = pageableTerritories;

function createBackgrid(collection){
    var columns = [{
        name: "id", // The key of the model attribute
        label: "ID", // The name to display in the header
        editable: false, // By default every cell in a column is editable, but *ID* shouldn't be
        // Defines a cell type, and ID is displayed as an integer without the ',' separating 1000s.
        cell: Backgrid.IntegerCell.extend({
            orderSeparator: ''
        })
    }, {
        name: "name",
        label: "Name",
        // The cell type can be a reference of a Backgrid.Cell subclass, any Backgrid.Cell subclass instances like *id* above, or a string
        cell: "string" // This is converted to "StringCell" and a corresponding class in the Backgrid package namespace is looked up
    }, {
        name: "pop",
        label: "Population",
        cell: "integer" // An integer cell is a number cell that displays humanized integers
    }, {
        name: "url",
        label: "URL",
        cell: "uri" // Renders the value in an HTML <a> element
    }];
    if ($(window).width() < 768){
        //okendoken. removing URL-column for screens smaller than 768px
        columns.splice(3,1)
    }
    var pageableGrid = new Backgrid.Grid({
        columns: columns,
        collection: collection,
        footer: Backgrid.Extension.Paginator.extend({
            //okendoken. rewrite template to add pagination class to container
            template: _.template('<tr><td colspan="<%= colspan %>"><ul class="pagination"><% _.each(handles, function (handle) { %><li <% if (handle.className) { %>class="<%= handle.className %>"<% } %>><a href="#" <% if (handle.title) {%> title="<%= handle.title %>"<% } %>><%= handle.label %></a></li><% }); %></ul></td></tr>')
        }),
        className: 'table table-striped table-editable no-margin'
    });
    $("#table-dynamic").html(pageableGrid.render().$el);


}

Solution

  • You need to trigger saving after the cell has been edited. This can be done simply by listening the change event of your Territory model. I have been using the following:

    var MyModel = Backbone.Model.extend({
        initialize : function() {
            this.on('change', function(model, options) {
                // Prevent save on update
                if (options.save === false)
                    return;
    
                model.save(_.clone(model.attributes), {});
            });
        },
        // Process and remove model unrelated stuff from server response
        parse : function(resp, options) {
            // pure model fetch
            if (!resp.data && !resp.notifications)
                return resp;
    
            // process notifications
            if (resp.notifications && resp.notifications.length)
                processNotifications(resp.notifications);
    
            return resp.data || {};
        },
        rollBack : function() {
            // Rollback to old data
            this.set(this.previousAttributes(), {save: false});
            // Trigger cell rendering
        },
        save : function(attrs, options) {
            options || (options = {});
    
            options.success = function(model, resp, options) {
                // Show optional success messages here if needed and
                // not in response from server
            };
    
            options.error = function(model, xhr, options) {
                var resp = JSON.parse(xhr.responseText);
                model.parse(resp, options);
                // Rollback to old data
                model.rollBack();
                model.trigger('backgrid:error');
            };
    
            // We get the correct data back from the server - prevent multiple saves
            options.save = false;
            options.data = JSON.stringify(attrs);
    
            Backbone.Model.prototype.save.call(this, attrs, options);
        }
    });
    

    This implementation gets all notifications from server (on success there is no feedback). Hence, notifications are filtered in model.parse method. If there are notifications, the data is in property data of response. However, if you show the feedback from the js, implement it in options.success and options.error