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

Cannot call method 'exitEditMode' of undefined #476

Closed glockjt closed 10 years ago

glockjt commented 10 years ago

I have a view that initially renders a new Backgrid.Grid then I have an event listener listen for another's view state change (its a drop down box, so I listen for the change event). When a selection is made that views event listener triggers an event for the view containing the backgrid. The event listener of the view containing the backgrid filters the collection and uses the filtered collection to create a new Backgrid.Grid. When a cell is clicked in this backgrid it results in the above error on exit of the cell. Below is the code of the view containing the backgrids, if you need more code let me know. Thanks in advance.

define([
    'jquery',
    'underscore',
    'backbone',
    'backgrid',
    'collections/scores',
    'models/scores',
    'text!templates/scorecard.html',
    'vent'
], function($, _, Backbone, Backgrid, ScoreCollection, ScoreModel, ScorecardTemplate, vent) {

    var columns = [{
        name: 'id',
        label: 'Course',
        cell: 'string'
    },
    {
        name: 'date',
        label: 'Date',
        cell: 'string'
    },
    {
        name: 'hole1',
        label: '1',
        cell: 'integer'
    },
    {
        name: 'hole2',
        label: '2',
        cell: 'integer'
    },
    {
        name: 'hole3',
        label: '3',
        cell: 'integer'
    },
    {
        name: 'hole4',
        label: '4',
        cell: 'integer'
    },
    {
        name: 'hole5',
        label: '5',
        cell: 'integer'
    },
    {
        name: 'hole6',
        label: '6',
        cell: 'integer'
    },
    {
        name: 'hole7',
        label: '7',
        cell: 'integer'
    },
    {
        name: 'hole8',
        label: '8',
        cell: 'integer'
    },
    {
        name: 'hole9',
        label: '9',
        cell: 'integer'
    },
    {
        name: 'out_tot',
        label: 'OUT',
        editable: false,
        cell: 'integer'
        // cell: Backgrid.IntegerCell.extend({
        //         className: 'out-cell'
        //       })
    },
    {
        name: 'hole10',
        label: '10',
        cell: 'integer'
    },
    {
        name: 'hole11',
        label: '11',
        cell: 'integer'
    },
    {
        name: 'hole12',
        label: '12',
        cell: 'integer'
    },
    {
        name: 'hole13',
        label: '13',
        cell: 'integer'
    },
    {
        name: 'hole14',
        label: '14',
        cell: 'integer'
    },
    {
        name: 'hole15',
        label: '15',
        cell: 'integer'
    },
    {
        name: 'hole16',
        label: '16',
        cell: 'integer'
    },
    {
        name: 'hole17',
        label: '17',
        cell: 'integer'
    },
    {
        name: 'hole18',
        label: '18',
        cell: 'integer'
    },
    {
        name: 'in_tot',
        label: 'IN',
        editable: false,
        cell: 'integer'
        // cell: Backgrid.IntegerCell.extend({
        //         className: 'in-cell'
        //       })
    },
    {
        name: 'tot',
        label: 'TOT',
        editable: false,
        cell: 'integer'
        // cell: Backgrid.IntegerCell.extend({
        //         className: 'tot-cell'
        //       })
    },
    {
        name: 'net',
        label: 'NET',
        editable: false,
        cell: 'integer'
        // cell: Backgrid.IntegerCell.extend({
        //         className: 'net-cell'
        //       })
    }
    ];

    var ScorecardView = Backbone.View.extend({
        el: $('.scorecard-container'),

        initialize: function() {
            _.bindAll(this, 'selectCourse');
            vent.bind('selectCourse', this.selectCourse);

            var self = this;

            this.collection = new ScoreCollection();

            this.collection.fetch({
                success: function() {
                    self.render();
                }
            });
        },

        render: function() {

            var backgridView = new Backgrid.Grid({
                id: 'pattern-style-a',
                columns: columns,
                collection: this.collection
            });

            this.$el.html(
                backgridView.render().$el
            );

            return this;
        },

        selectCourse: function(courseId) {

            var selector = { courseId: parseInt(courseId) };
            var selected = new ScoreCollection();
            var matcher = function(model) {
                return model.byCourseId(selector);
            }

            selected.reset( this.collection.filter(matcher) );

            var courseBackgridView = new Backgrid.Grid({
                id: 'pattern-style-a',
                columns: columns,
                collection: selected
            });

            this.$el.html(
                courseBackgridView.render().$el
            );
        }
    });

    return ScorecardView;
});
wyuenho commented 10 years ago

Which version of backgrid are you using and are you using any custom cells?

wyuenho commented 10 years ago

This issue has been fixed last year. @glockjt let me know if you still have this problem.

gdw2 commented 10 years ago

Does this fiddle demonstrate the problem?:

http://jsfiddle.net/gdw2/61v9r02z/3/

gdw2 commented 10 years ago

Another example with no extra plugins:

http://jsfiddle.net/gdw2/61v9r02z/6/

The gotcha here is that I'm rendering two backgrids, replacing the first with the second. If I grid1.remove() the first (see fiddle), then it works fine. I'm guessing its best-practice to .remove() views. Can anybody speak to this? Is it okay that this is necessary?