shutterstock / rickshaw

JavaScript toolkit for creating interactive real-time graphs
https://shutterstock.github.io/rickshaw
MIT License
6.53k stars 939 forks source link

Using Rickshaw with backbone.js: Cannot call getPropertyValue of Null #172

Closed andreas-marschke closed 11 years ago

andreas-marschke commented 11 years ago

Hi!

When using http://backbonejs.com and rickshaw I get problems rendering my Graphs.

Here is an example of what I am trying to do:


(function (window, document, undefined) {

    var State = Backbone.Model.extend({
    });
    var States = Backbone.Collection.extend({
        model: State,
        url: '/json',
        initialize: function() {
            this.palette = new Rickshaw.Color.Palette({scheme: "classic9"});
            this.series = new Rickshaw.Series({
                color: this.palette.color(),
                data: this.toJSON()
            });
        },
        fetch: function(callback) {
            var that = this;
            $.ajax({
                type: 'GET',
                url: this.url,
                success: function(data) {
                    that.add(new State(data));
                    callback;
                }
            });
        }
    });

    var StateView = Backbone.View.extend({
        collection: States,
        initialize: function() {
            this.graph = new Rickshaw.Graph({
                element: this.$el,
                width: 580,
                height: 230,
                series: this.collection.series
            });
            this.collection.on('sync',this.render());
        },
        render: function() {
            this.graph.render();
        }
    });

    var states = new States();
    var view = new StateView({el: $('#root'), collection: states});
    setIntervall(function() {
        states.fetch(function() {
            console.log(states.length);
        });
    },3000);

})(this, this.document);

The element $('#root') already exists in the document. The data is appended to the Series when it is fetched from the server.

The error I get is: Uncaught TypeError: Cannot call method 'getPropertyValue' of null Here is the full trace where script.js is the script pasted above:

Uncaught TypeError: Cannot call method 'getPropertyValue' of null rickshaw.js:593
setSize rickshaw.js:593
initialize rickshaw.js:406
Rickshaw.Graph rickshaw.js:605
Backbone.View.extend.initialize script.js:35
Backbone.View backbone.js:1200
child backbone.js:1448
(anonymous function) script.js:49
(anonymous function) script.js:56

Backbone.js and Rickshaw.js are the latest dev checkouts from github.com.

Thanks in advance,

Andreas Marschke.

UPDATE: In case somebody wants to quickly see this problem in Action here is a page: http://www.andreas-marschke.name/debug.html

markmo commented 11 years ago

Hi Andreas, Having just run into this myself, I believe the issue is that Rickshaw is expecting a DOM element not a jQuery wrapped element, so using this.el instead of this.$el for element should work.

Best regards, Mark

andreas-marschke commented 11 years ago

Thanks!

I looked into it with your advice in mind and apparently that worked. Another issue I ran into doing this was figuring out when the element actually reacts and fires the appropriate event. Anyway: Here is the solution:


(function (window, document, undefined) {

    var State = Backbone.Model.extend({});
    var States = Backbone.Collection.extend({
        model: State,
        url: '/json',
        initialize: function() {
            _.extend(this,Backbone.Events);
            this.palette = new Rickshaw.Color.Palette({scheme: "classic9"});
            this.series = new Rickshaw.Series({
                color: this.palette.color(),
                data: []
            });
        },
        fetch: function() {
            var that = this;
            $.ajax({
                type: 'GET',
                url: this.url,
                success: function(data) {
                    that.add(new State(data));
                    that.series.addData(data);
                    if(that.length === 1) {
                        that.trigger('first-data');
                    }
                    that.trigger('series-update');
                }
            });
        }
    });

    var StateView = Backbone.View.extend({
        collection: States,
        initialize: function() {
            this.graph = new Rickshaw.Graph({
                element: this.el,
                width: 580,
                height: 230,
                series: this.collection.series
            });
            var that = this;
            this.collection.on('series-update',function() { 
                that.render();
            });
        },
        render: function() {
            this.graph.render();
        }
    });

    var states = new States();

    setInterval(function() {
        states.fetch();
    },1000);
    var view;
    states.on('first-data', function() { 
        view = new StateView({el: $('#root'), collection: states});
    });

})(this, this.document);
dchester commented 11 years ago

Looks like we're all set here.