Question

I've been trying how to do this for a couple days, as well as googling for a built solution but sadly no success.

I'm building an Admin section for a custom made e-commerce product. This Admin area, is entirely built as an SPA (Single Page Application), that dynamically loads 'ko' Templates and their data, both thru AJAX calls.

Now, the issue at hand is that I'd like to include Charts, Pies, and other data visualization elements inside this ko templates (i.e. Summarized data shown nicely on a graph, at the Dashboard template).

For this, I'm working on a 'KO Custom Binding' for the Google Chart API, which is getting properly called.

This is what I have till now, that creates a fixed Chart (adapted to KO from: this sample)

ko.bindingHandlers.googleChart = {
init: function (element, valueAccessor, allBindingsAccesor, viewModel, bindingContext) {

    google.load("visualization", "1", { packages: ["corechart"] });
    google.setOnLoadCallback(function () {
        var data = new google.visualization.DataTable();
        data.addColumn('string', 'Year');
        data.addColumn('number', 'Revenue');
        data.addColumn('number', 'Average Revenue');
        data.addRows([
          ['2004', 1000, 630],
          ['2005', 1170, 630],
          ['2006', 660, 630],
          ['2007', 1030, 630]
        ]);

        var options = {
            title: 'Revenue by Year',
            seriesType: "bars",
            series: { 1: { type: "line" } },
            vAxis: {
                title: 'Year',
                titleTextStyle: { color: 'red' }
            },
            colors: ['red', 'black']
        };

        var chart = new google.visualization.ComboChart($(element));
        chart.draw(data, options);
    });
}};

Then, from the template, I call the binding, passing 'false' by now, or any dummy ko.observable from the viewModel.

<script type="text/html" id="dashboard-admin-template">
    <div data-bind="googleChart: false"></div>    
</script>

Now, finally (sorry it took so long), the issue I'm having:

After, google.load("visualization", "1", { packages: ["corechart"] });, the 'element' contents become inaccessible (can't post the capture from my IDE as I'm a newbie on reputation matters), making the callback to fail, and not rendering the chart. The 'element' contents are all there, and accesible, before calling 'google.load'. Then getting a Javascript runtime error: Access is denied when the callback gets called.

Hope to get some help as I'm stuck on this one. Thanks! Luis

Was it helpful?

Solution

Let me restate the proper answer.

  1. Take the google.load("visualization"... out of the custom binding code
  2. Avoid calling the google.setOnLoadCallback(function()... executing the inner code directly by itself.

Here's how the binding looks now...

google.load("visualization", "1", { packages: ["corechart"] });
ko.bindingHandlers.googleChart = {
init: function (element, valueAccessor, allBindingsAccesor, viewModel, bindingContext) {

    //TODO: load & handle visualization data using the 'valueAccessor'

    var data = new google.visualization.DataTable();
    data.addColumn('string', 'Year');
    data.addColumn('number', 'Revenue');
    data.addColumn('number', 'Average Revenue');
    data.addRows([
        ['2004', 1000, 630],
        ['2005', 1170, 630],
        ['2006', 660, 630],
        ['2007', 1030, 630]
    ]);

    var options = {
        title: 'Revenue by Year',
        seriesType: "bars",
        series: { 1: { type: "line" } },
        vAxis: {
            title: 'Year',
            titleTextStyle: { color: 'red' }
        },
        colors: ['red', 'black']
    };

    var chart = new google.visualization.ComboChart(element);
    chart.draw(data, options);
}};

Hope this help any of you working on a similar matter!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top