How do I update a KendoUI chart via javascript JSON?

Secret Squirrel picture Secret Squirrel · Dec 18, 2013 · Viewed 7.7k times · Source

So I have a chart which is configured using the MVC style configuration...

@(Html.Kendo().Chart<DIMVC.ViewModel.CompanyProduction>(Model.CompanyProduction)
     .Name("Chart")
     .Title("Files sent")
     .Legend(legend => legend
     .Position(ChartLegendPosition.Bottom)
 )
 .ChartArea(chartArea => chartArea
     .Background("transparent")
 )
 .SeriesDefaults(seriesDefaults =>
     seriesDefaults.Line().Style(ChartLineStyle.Smooth)
 )
.Series(series => { 
     series.Line(model => model.SentFiles).Name("Sent Files");
     ...  { lots more series added here }
}
.CategoryAxis(axis => axis
     .Categories(model => model.MonthDisplay)
     .Labels(labels => labels.Rotation(-90))
)
.ValueAxis(axis => axis.Numeric()
     .Labels(labels => labels.Format("{0:N0}"))
     .MajorUnit(10000)
)
.Tooltip(tooltip => tooltip
    .Visible(true)
    .Format("{0:N0}")
)
.Events(e => e
    .SeriesClick("onSeriesClick")
)

)

I also have a slider on the page. When the slider value is changed I handle this event.

@(Html.Kendo().RangeSlider()
    .Name("yearRange")
    .Min(2000)
    .Max(DateTime.Today.Year)
    .SmallStep(1)
    .LargeStep(5)
    .Values(Model.MinYear, Model.MaxYear)
    .Events(e => e.Change("yearRangeChange"))
 )

javascript method

function yearRangeChange(e)
{
     var url = "/FetchData/";

     $.ajax({
         type: "GET",
         url: url,
         data: { startYear: e.values[0], endYear: e.values[1] },
         dataType: "json",
         success: function (json) {

        $("#DINETChart").kendoChart({
            dataSource: {
               data: json
        }
    });

     var chart = $("#DINETChart").data("kendoChart");
    chart.refresh();
 }
 }); 
 }

now when the chart is updated the grid is just blank.

The json request is successfully called and the data is retrieved. but after the chart is populated the chart is blank.

has anyone got any suggestions?

* EDIT *

adding a sample of the JSON returned

"[{\"CompanyID\":1,\"Year\":2011,\"Month\":8,\"SentFiles\":1666,\"ReceivedFiles\":1632,\"SentData\":12803.674593292486,\"ReceivedData\":11908.047586546765,\"Note\":null,\"MonthDisplay\":\"Aug\",\"CompanyDisplay\":null},{\"CompanyID\":1,\"Year\":2013,\"Month\":10,\"SentFiles\":21004,\"ReceivedFiles\":20387,\"SentData\":157376.825542573,\"ReceivedData\":152878.87845794103,\"Note\":null,\"MonthDisplay\":\"Oct\",\"CompanyDisplay\":null},{\"CompanyID\":1,\"Year\":2013,\"Month\":4,\"SentFiles\":9989,\"ReceivedFiles\":9880,\"SentData\":74913.53277995327,\"ReceivedData\":75145.16331588416,\"Note\":null,\"MonthDisplay\":\"Apr\",\"CompanyDisplay\":null},{\"CompanyID\":1,\"Year\":2013,\"Month\":11,\"SentFiles\":25956,\"ReceivedFiles\":25249,\"SentData\":196155.8977337967,\"ReceivedData\":189320.44546897494,\"Note\":null,\"MonthDisplay\":\"Nov\",\"CompanyDisplay\":null}]"

I would also like to point out that if I add this

.DataSource(ds => ds.Read(read =>
    read.Action("FetchData", "Home", new { startYear = 2012, endYear = 2013 })
))

to my chart configuration, this will populate the chart fine, without using the page Model. i.e. The data is correct for the chart.

Answer

Lars H&#246;ppner picture Lars Höppner · Dec 18, 2013

The data source expects an array as value for its data, but it looks like the json variable you're assigning contains a JSON string (at least if the string you added to the question is what you're seeing on the client in the json var). jQuery should normally parse that for you if you set dataType to "json" (not sure why that is not happening for you - you should double check that the dataType param is set correctly).

You can try parsing it yourself; apart from that, you should also use chart.setDataSource() instead of creating a new chart. They way you're doing it now, you're simply replacing your original chart with its configuration with a chart that has no configuration. Try something like this in your callback:

var data = JSON.parse(json);
var chart = $("#DINETChart").data("kendoChart");
var dataSource = new kendo.data.DataSource({
    data: data
});
chart.setDataSource(dataSource);

Note that in your yearRangeChange function, you're trying to call refresh on the chart outside of your ajax success call. You don't need to refresh when you use setDataSource, but even if you needed to do that, it would have to be in the callback. Otherwise it happens before the ajax call completes.