Search code examples
javascriptbackbone.jsbackgrid

Avoid clicking twice to begin editing boolean (checkbox) cell in Backgrid


We are using Backgrid and have discovered that to begin editing a "boolean" (checkbox) cell in Backgrid, you must click twice: the first click is ignored and does not toggle the state of the checkbox. Ideally we would get to the root of what is causing this behavior (e.g. is preventDefault being called) and solve it there, but I at first I tried a different approach with the following extension of BooleanCell's enterEditMode method which seemed like a logical place since it was upon entering edit mode that the checkbox click was being ignored.

Problem is my attempt also toggles the state of the previously edited checkbox. Here is the code.

var BooleanCell = Backgrid.BooleanCell.extend({
    /*
    * see https://github.com/wyuenho/backgrid/issues/557
    */
    enterEditMode: function () {
        Backgrid.BooleanCell.prototype.enterEditMode.apply(this, arguments);
        var checkbox = this.$('input');
        checkbox.prop('checked', !checkbox.prop('checked'));
    }
});

Solution

  • The following seems to work:

    var BooleanCell = Backgrid.BooleanCell.extend({
        editor: Backgrid.BooleanCellEditor.extend({
            render: function () {
                var model = this.model;
                var columnName = this.column.get("name");
                var val = this.formatter.fromRaw(model.get(columnName), model);
    
                /*
                 * Toggle checked property since a click is what triggered enterEditMode
                */
                this.$el.prop("checked", !val);
                model.set(columnName, !val);
    
                return this;
            }
        })
    });
    

    This is because the render method gets called by Backgrid.BooleanCell's enterEditMode method on click, and said method destroys and re-creates the checkbox as follows but in so doing loses the checked state (after the click) of the original "non-edit-mode" checkbox

      this.$el.empty();
      this.$el.append(this.currentEditor.$el);
      this.currentEditor.render();