Friday 24 May 2013

How to add multiple series dynamically in kendo UI chart

Method1
<script type="text/javascript">

    var dataSource;

    function GetSelectedDuration() {
        return $("input:radio[name=Duration]:checked").val();
    }

    function ReBindDataSource() {
        dataSource = new kendo.data.DataSource({
            transport: {
                read: {
                    url: "http://localhost/Home/GetDummydata",
                    cache: false,
                    data: { Duration: GetSelectedDuration() }
                }
            }
        });

        dataSource.fetch(function () {
            if (dataSource._data.length > 0) {
                var keys = Object.keys(dataSource._data[0]);
                ReDrawChart(keys);
            }
        });
    }


    function radioClicks() {
        ReBindDataSource();
    }


    $(document).ready(function () {

        $("input:radio[name=Duration]").bind("click", radioClicks);

        $("#mychart").kendoChart({
            title: {
                text: "Dynamic Column"
            },
            legend: {
                position: "top"
            },
            seriesDefaults: {
                type: "column"
            },
            valueAxis: {
                labels: {
                    format: "{0}%"
                },
                line: {
                    visible: true
                }
            },
            categoryAxis: {
                field: "Field1",
                majorGridLines: {
                    visible: false
                }
            },
            tooltip: {
                visible: true,
                format: "{0}%",
                template: "#= series.field #: #= value #%"
            }

        });


        ReBindDataSource();
    });

    // Add series dynamically in chart
    function ReDrawChart(keys) {

        var InvalidColumnName = new Array("_events", "uid", "parent", "Field1");

        var chart = $("#mychart").data("kendoChart");
        var chartOptions = chart.options;

        var SeriesCount = 0;
        for (var k = 0; k < keys.length; k++) {
            var mykey = keys[k];
            if ($.inArray(mykey, InvalidColumnName) == -1) {
                chartOptions.series.push(new Object());
                chartOptions.series[SeriesCount].field = mykey;
                SeriesCount++;
            }
        }
        chart.setDataSource(dataSource);
        chart.redraw();
    }

</script>
<div>
<input checked="checked" name="Duration" type="radio" value="1" />Annully
    <input name="Duration" type="radio" value="2" />Monthly
    <input name="Duration" type="radio" value="3" />Weekly
    <input name="Duration" type="radio" value="4" />Daily
</div>
<div id="mychart">
</div>
Below code snippet is only for reference to create Dummy data in MVC. Controller
public class HomeController : Controller
{
    [AllowAnonymous]
    [HttpGet]
    public JsonResult GetDummydata(int Duration)
    {
        List>TestModels> models = GetDummyData(Duration);

        return Json(models, JsonRequestBehavior.AllowGet);
    }

    public List<TestModels> GetDummyData(int Duration)
    {
        List<TestModels> models = new List<TestModels>();

        switch (Duration)
        {
            case (int)DurationType.Annully:

                TestModels testModel = new TestModels();
                testModel.Field1 = "Annully";
                testModel.Field2 = 20;
                testModel.Field3 = 50;
                testModel.Field4 = 70;
                models.Add(testModel);

                break;
            case (int)DurationType.Monthly:

                TestModels testModel2 = new TestModels();
                testModel2.Field1 = "Monthly";
                testModel2.Field2 = 50;
                testModel2.Field3 = 50;
                testModel2.Field4 = 50;
                models.Add(testModel2);

                break;
            case (int)DurationType.Weekly:
                TestModels testModel3 = new TestModels();
                testModel3.Field1 = "Weekly";
                testModel3.Field2 = 70;
                testModel3.Field3 = 10;
                testModel3.Field4 = 90;
                models.Add(testModel3);
                break;
            case (int)DurationType.Daily:
                TestModels testModel4 = new TestModels();
                testModel4.Field1 = "Daily";
                testModel4.Field2 = 11;
                testModel4.Field3 = 111;
                testModel4.Field4 = 1111;
                models.Add(testModel4);
                break;

        }

        return models;
    }
}
Model
[Serializable]
public class TestModels
{   
        public string Field1 { get; set; }
        public int Field2 { get; set; }
        public int Field3 { get; set; }
        public int Field4 { get; set; }
}

Method2


<script type="text/javascript">

    var dataSource;

    function radioClicks() {
        getDataSource();
    }


    function GetSelectedDuration() {
        return $("input:radio[name=Duration]:checked").val();
    }

    function getDataSource() {
        dataSource = new kendo.data.DataSource({
            transport: {
                read: {
                    url: "http://localhost:2116/Home/GetDummydata2",
                    cache: false,
                    data: { Duration: GetSelectedDuration() }
                }
            }
        });

        dataSource.fetch(function () {
            GenerateChartFromData();
        });
    }

    function GenerateChartFromData() {

        var chartSeries = [];

        var keys = Object.keys(dataSource._data[0]);
        var InvalidColumnName = new Array("_events", "uid", "parent", "Price");

        for (var k = 0; k < keys.length; k++) {
            var mykey = keys[k];
            if ($.inArray(mykey, InvalidColumnName) == -1) {
                chartSeries.push({ xField: "Price", yField: mykey, name: mykey.replace("_", ""), style: "smooth" });
            }
        }

        var titletxt = "Title text comes here - ";

        switch (parseInt(GetSelectedDuration())) {
            case 1:
                titletxt += "on " + chartSeries[0].name;
                break;
            case 2:
                titletxt += "with multiple series";
                break;
        }



        $("#chart").kendoChart({
            title: {
                text: titletxt
            },
            legend: {
                position: "right"
            },
            dataSource: dataSource,
            seriesDefaults: {
                type: "scatterLine"
            },
            series: chartSeries,
            xAxis: {
                min: 19,
                max: 46,
                labels: {
                    format: "{0}"
                }
            },
            yAxis: {
                // min: 80,
                labels: {
                    format: "{0}"
                },
                title: {
                    text: "testTitle"
                }
            }
        });

    }

    $(document).ready(function () {

        $("input:radio[name=Duration]").bind("click", radioClicks);

        getDataSource();
    });

</script>
<div>
<input checked="checked" name="Duration" type="radio" value="1" />Single series
    <input name="Duration" type="radio" value="2" />multiple series
</div>
<div id="chart">
</div>
Below code snippet is only for reference to create Dummy data in MVC. Controller
public JsonResult GetDummydata2(int Duration)
{


    switch (Duration)
    {
        case 1:

            List<testmodels_1> lst = new List<testmodels_1>();

            for (int i = 0; i < 20; i++)
            {
                int dtValue = 0;

                if (i < 10)
                {
                    dtValue = -478;
                }
                else if (i < 12)
                {
                    dtValue = -78;
                }
                else if (i < 14)
                {
                    dtValue = -28;
                }
                else if (i < 16)
                {
                    dtValue = 22;
                }
                else if (i < 18)
                {
                    dtValue = 72;
                }
                else
                {
                    dtValue = 122;
                }

                lst.Add(new TestModels_1() { Price = 20 + i, _07072014 = dtValue });
                lst.Add(new TestModels_1() { Price = 20.5M + i, _07072014 = dtValue });


            }

            return Json(lst, JsonRequestBehavior.AllowGet);
            break;
        case 2:

            List<testmodels_2> lst1 = new List<testmodels_2>();

            for (int j = 0; j < 20; j++)
            {
                int dtValue1 = 0;

                if (j < 10)
                {
                    dtValue1 = -478;
                }
                else if (j < 12)
                {
                    dtValue1 = -78;
                }
                else if (j < 14)
                {
                    dtValue1 = -28;
                }
                else if (j < 16)
                {
                    dtValue1 = 22;
                }
                else if (j < 18)
                {
                    dtValue1 = 72;
                }
                else
                {
                    dtValue1 = 122;
                }

                lst1.Add(new TestModels_2() { Price = 20 + j, _07072014 = dtValue1, _08072014 = dtValue1 - 20, _08082014 = dtValue1 - 30 });
                lst1.Add(new TestModels_2() { Price = 20.5M + j, _07072014 = dtValue1, _08072014 = dtValue1 - 70, _08082014 = dtValue1 - 80 });


            }
            return Json(lst1, JsonRequestBehavior.AllowGet);
            break;


    }


    return Json(new { IsError = true }, JsonRequestBehavior.AllowGet);
}

public DateTime? GetDateTimeFromString(string strDateTime)
{
    if (!string.IsNullOrEmpty(strDateTime.Trim()))
    {
        string pattern = "dd/MM/yyy";
        DateTime parsedDate;

        if (DateTime.TryParseExact(strDateTime.Trim(), pattern, null, System.Globalization.DateTimeStyles.None, out parsedDate))
        {
            return parsedDate;
        }
    }

    return null;
}
Model
[Serializable]
public class TestModels_1
{
        public decimal Price { get; set; }
        public decimal _07072014 { get; set; }
}

public class TestModels_2
    {
        public decimal Price { get; set; }
        public decimal _07072014 { get; set; }
        public decimal _08072014 { get; set; }
        public decimal _08082014 { get; set; }
}

DOWNLOAD DEMO

16 comments:

  1. nice job Jayesh,

    I have a table in which there are fields including ParamName, ParamValue, ParamType and LogDate. I can display them in a ScatterLine type of the Kendo Chart without difficulty if I have only one ParamName per ParamType. because I can group them by ParamType. but if I have more than one parameters which have the same type I couldn't group them. here is my code:

    @(Html.Kendo().Chart()
    .Name("chart")
    .Title("Main Core Trends")
    .DataSource(dataSource => dataSource.Read(read => read.Action("GetMainTrend", Params"))
    .Group(group => group.Add(model => model.ParamType))
    .Sort(sort => sort.Add(model => model.LogDate).Ascending())
    )
    .Series(series => series.ScatterLine(model => model.LogDate, model => model.ParamValue)
    .GroupNameTemplate("#= group.value # ").Markers(marker => marker.Visible(false)).Width(2))
    .Legend(legend => legend
    .Position(ChartLegendPosition.Bottom)
    )
    .YAxis(y => y.Numeric()
    .Labels(labels => labels.Format("0:N0"))
    )
    .XAxis(axis => axis.Date()
    .Labels(labels => labels.Format("M-d HH:m").Rotation(90).Step(1))
    )
    .Tooltip(tooltip => tooltip
    .Visible(true)
    )
    )

    ReplyDelete
  2. possible to upload the source code solution file? Thanks.

    ReplyDelete
  3. Demo link : http://jmp.sh/v/2WYVzKgVTnALqfuwrW4c

    ReplyDelete
  4. How to display the field and name for the chart legend?

    ReplyDelete
  5. Hi Jayesh,Woow Grate work.
    And thanks for the demo link too.Do u have demo(sample) project for stacked bar chart
    Thanks
    Manoj

    ReplyDelete
  6. Hi

    I want to add 2 header lines in kendo json grid.

    ReplyDelete
  7. @Manoj, Sorry i don't have any demo for this.
    @Anonymous, Can you please provide more detail?

    ReplyDelete
  8. The article title should read "multiple bar chart series", not line as the example does not include data relating to both axis. If you can show an example on how to do that much appreciated.

    ReplyDelete
  9. I have 2 series graph I want to change the date duration on category axis from weeks to months dynamically.. I can do that on single axis graph but its not working for multi axis graph can you please help me ?

    ReplyDelete
  10. This was incredibly helpful. Instead of using the InvalidColumnName = new Array("_events", "uid", "parent", "Field1") test against the Keys, I used the toJSON method on my Datasource Model point to extract the raw Javascript Object. This wouldn't help on the "Field1" filter, but for my data it worked well, and eliminated any future issues if methods/property names are changed or added.

    ReplyDelete
  11. Hi Jayesh

    This is very nice solution but i want to ask a question??

    Is it possible to change dynamically chart type?? like select "bar","line","pie","area"

    ReplyDelete
  12. No we can not dynamically change chart types. Because each chart's has different properties and declarations.

    ReplyDelete
  13. @Jayesh Goyani: Is it possible to set custom colors to series(Without using material theme)?

    ReplyDelete
    Replies
    1. I found the solution. Thank You

      Delete
  14. "Great blog created by you. I read your blog, its best and useful information. You have done a great work. Super blogging and keep it up.php jobs in hyderabad.
    "

    ReplyDelete