Looping problem - dataBound event calls setOptions which then fires dataBound event

3 posts, 0 answers
  1. Joshua
    Joshua avatar
    2 posts
    Member since:
    May 2016

    Posted 28 Sep Link to this post

    I have a html/javascript chart which I populate via an ajax call. On dataBound, i resize the chart xAxis max and draw plotbands based on the values bound to the grid. Unfortunately, the setOptions call seems to then fire the dataBound event again... and around and around it goes in an endless loop. I got around this by setting a flag so that it only processes the first time. However, the issue I now face is that when I pull new data into the chart later (say because the user expanded the data ranges), i cant reset that flag and let it fire the code in the dataBound event. So, when the user expands the date ranges there is a good chance that my poltbands and axiscrossing settings will be wrong. Any advice?  See below for code...

     

    $.ajax({
            type: "POST",
            data: JSON.stringify({
                startDate: $('#txtDateRangeFilter').data('daterangepicker').startDate,
                endDate: $('#txtDateRangeFilter').data('daterangepicker').endDate
            }),
            url: "/User/EChart",
            contentType: "application/json",
            dataType: 'json'
        })
            .done(function (data) {
                var plotbandloaded = false;

                $('#currentDuration').text(Math.round(data.userGoalDetails.DurationHours * 100) / 100 + " hrs");
                $('#goalDuration').text(Math.round(data.userGoalDetails.Goal * 100) / 100 + " hrs");
                $("#chartE").kendoChart(
                {
                    dataSource: {
                        data: data.userActivity
                    },
                    sort: {
                        field: "CreateDateTime",
                        dir: "asc"
                    },
                    title: {
                        text: ""
                    },
                    legend: {
                        position: "bottom"
                    },
                    chartArea: {
                        background: "",
                        width: 300,
                        height: 190
                    },
                    seriesDefaults: {
                        type: "line",
                        style: "smooth"
                    },
                    series: [
                        {
                            field: "Minutes",
                            name: "Minutes",
                            axis: "Minutes",
                            color: "#4D4D4D",
                            type: "column"
                        }, {
                            name: "Count",
                            field: "Count",
                            axis: "Count",
                            color: "#00B5A3",
                            type: "line"
                        }
                    ],
                    valueAxes: [{
                        name: "Minutes",
                        color: "#4D4D4D"
                    }, {
                        name: "Count",
                        color: "#00B5A3"
                    }],
                    categoryAxis: {
                        field: "Day",
                        majorGridLines: {
                            visible: false
                        },
                        axisCrossingValues: [0, 50],
                        labels: {
                            rotation: "auto"
                        }
                    },
                    tooltip: {
                        visible: true,
                        format: "{0}%",
                        template: "#= series.name #: #= value #"
                    },
                    dataBound: function (e) {
                        setTimeout(function () {
                            if (plotbandloaded == false) {
                                var goal = Math.round((data.userGoalDetails.Goal * 60) * 100) / 100;
                                var goalTo = goal + (goal * .025);
                                var setMax = goal + (goalTo * .15);
                                var chart = $('#chartE').data("kendoChart");
                                var axisCrossing = chart.options.series[1].data.length + 1;
                                var options = {
                                    valueAxes: [{
                                            name: "Minutes",
                                            color: "#4D4D4D",
                                            max: setMax,
                                            plotBands: [{
                                                from: goal,
                                                to: goalTo,
                                                color: "#c00",
                                                opacity: 0.3
                                            }]
                                        }, {
                                            name: "Count",
                                            color: "#00B5A3"
                                        }],
                                    categoryAxis: { axisCrossingValues: [0, axisCrossing] }
                                    };

                                plotbandloaded = true;
                                chart.setOptions(options);
                            };
                        }, 100)
                    }
                });

            });

  2. Joshua
    Joshua avatar
    2 posts
    Member since:
    May 2016

    Posted 29 Sep in reply to Joshua Link to this post

    Is there a better way to do this?

     

    Anyone, anyone?...

     

    This is what I feel like right now...

    [https://www.youtube.com/watch?v=uhiCFdWeQfA]

  3. Kendo UI is VS 2017 Ready
  4. Dimo
    Admin
    Dimo avatar
    8330 posts

    Posted 03 Oct Link to this post

    Hi Joshua,

    The Chart's setOptions method recreates and rebinds the widget, so the observed endless loop is expected. Generally, we do not recommend executing a widget's setOptions method in the same widget's event handler.

    In this specific case, a possible alternative is to manipulate the chart options directly in the dataBound event. No setTimeout will be needed. A similar approach is used here:

    http://docs.telerik.com/kendo-ui/controls/charts/how-to/grouped-line-chart-different-markers

    function onDB(e) {
      var chart = e.sender,
          options = chart.options,
          series = options.series;
     
      series[0].markers.type = "triangle";
      series[1].markers.type = "cross";
      series[2].markers.type = "square";
    }

    Please note that this is not something that works for all Kendo UI widgets.

    Regards,
    Dimo
    Telerik by Progress
    Get started with Kendo UI in days. Online training courses help you quickly implement components into your apps.
Back to Top