cloudflarearchive / backgrid

Finally, an easily stylable semantic HTML data grid widget with a Javascript API that doesn't suck.
http://backgridjs.com
MIT License
2.01k stars 325 forks source link

Backgrid REST design: ID is not passed automatically in the URL #284

Closed tasas closed 11 years ago

tasas commented 11 years ago

My trivial CRUD REST design looks like this:

create: [USERID]/weights/ read: [USERID]/weights/[ITEMID] update: [USERID]/weights/[ITEMID] delete: [USERID]/weights/[ITEMID]

I tried backgrid and methodToURL. All I've been achieving is:

create: [USERID]/weights/ read: [USERID]/weights/ update: [USERID]/weights/ delete: [USERID]/weights/

i.e. the ITEMID isn't passed at all. Even without methodToURL backgrid does not pass the ITEMID. Now I'm lost. Any suggestions?

Here's my impl. attempt:

http://pastebin.com/v0sBDL7p

wyuenho commented 11 years ago

Try this:

var Weight = Backbone.Model.extend({
    initialize: function() {
        Backbone.Model.prototype.initialize.apply(this, arguments);
        this.on("change", function(model, options) {
            console.log("Saving change");
            if (options && options.save === false)
                return;
            model.save();
        });
    }   
});

var PageableWeightTable = Backbone.PageableCollection.extend({
    model: Weight,
    state: {
        pageSize: 10
    },
    mode: "client",
    initialize: function (options) {
        this.sesUserId = options.sesUserId;
        this.url = '/' + this.sesUserId + '/weights';
    }
});

var weightTable = new PageableWeightTable(null, {sesUserId: 1});
var grid = new Backgrid.Grid({
    columns: [{
        name: "",
        cell: "select-row",
        headerCell: "select-all"
    }, {
       ... // the rest of your column definitions
    }]
    collection: weightTable
});

var $divWeightTable = $("#divweighttable");
$divWeightTable.append(grid.render().$el);

var paginator = new Backgrid.Extension.Paginator({
    collection: weightTable
});

$divWeightTable.append(paginator.render().$el);

weightTable.fetch( { reset: true } );

Please do note that if you are using backbone-pageable, you should be using at least https://github.com/jashkenas/backbone/commit/e91b36c0cb0ac877082d3367a8df44d21919e85c which addresses this issue: https://github.com/wyuenho/backbone-pageable/issues/70

tasas commented 11 years ago

Thank you very much for bothering. I'm getting a TypeError: options is null [Break On This Error]

this.sesUserId = options.sesUserId;

error even though I'm calling

var weightTable = new PageableWeightTable(null, { sesUserId: 1});

???

O, and I'm indeed using the latest master of backbone

tasas commented 11 years ago

I've updated all js-es to the latest master version, i.e. backbone-pageable now runs on 1.3.1. The type error is gone now.

Unfortunately, your solution didn't fix my problem.

All URLs still without the id :-(

create: [USERID]/weights/ read: [USERID]/weights/ update: [USERID]/weights/ delete: [USERID]/weights/

tasas commented 11 years ago

All right, I give up with pageable. I'm trying ordinary backbone.collection now. Put works fine, however, my delete implementation does not work:


// get UserID from html doc
var sesUserId = $("#userId").attr("value");

var Weight = Backbone.Model.extend({
    urlRoot: '/' + this.sesUserId + '/weights',
    initialize: function() {
        Backbone.Model.prototype.initialize.apply(this, arguments);
        this.on("change", function(model, options) {
            console.log("Saving change");
            if (options && options.save === false)
                return;
            model.save();
        });
    }   
});   

var WeightTable = Backbone.Collection.extend({
    model: Weight,
    url: '/' + sesUserId +'/weights/'
});

var DeleteCell = Backgrid.Cell.extend({
    template: _.template('<button class=backgridDeleteButton>Delete</button>'),
    className: "custom-delete-cell",
    events: {
        "click": "deleteRow"
    },
    deleteRow: function(e) {
        console.log("Deleting id " + this.model.id);
        e.preventDefault();
        this.model.destroy(this.model);
    },
    render: function() {
        this.$el.html(this.template());
        this.delegateEvents();
        return this;
    }
});

The delete URL looks pretty messed up:

"NetworkError: 404 Not Found - https://*****/function%20()%20%7B%20%20%20%20%20%20var%20base%20=%20_.result(this,%20%27urlRoot%27)%20||%20_.result(this.collection,%20%27url%27)%20||%20urlError();%20%20%20%20%20%20if%20(this.isNew())%20return%20base;%20%20%20%20%20%20return%20base%20+%20(base.charAt(base.length%20-%201)%20===%20%27/%27%20?%20%27%27%20:%20%27/%27)%20+%20encodeURIComponent(this.id);%20%20%20%20}"

Any idea how I could use delete properly? I'd be happy then

wyuenho commented 11 years ago

You need to use at least jashkenas/backbone@e91b36c to make pageable work. It's a backbone bug that's messing up with the URL generation.

You also don't need to put the url into the collection.

Also, your model.destroy() call is wrong.

http://backbonejs.org/#Model-destroy

Try this instead:

this.model.destroy();
tasas commented 11 years ago

Hi Wyuenho

Thank you so much for your advice. this.model.destroy(); did it :-)

Best wishes & carry on the good work. Backgrid is gonna be legen - dary with V1.0!

Cheers