2

I am using an MVC Razor foreach to render charts, sometimes over 150.

This is how I generate the script:

@{chartCount = 0;}
@foreach (var item in Model.ChartRows.Where(m => !m.SummaryRow))
    { 
        $('#container_@(chartCount)').highcharts({ 
             //code removed for brevity
        });  
        chartCount++;
    }

And then in my HTML I use this to render the containers:

@for (int i = 0; i < chartCount; i++)
    {
        <div id="container_@(i)"></div><br />
    }

However, when there are 100's of items in ChartRows, the page can take a long time to load before suddenly all of the charts appear. I have taken a look on the HighCharts website and have found a chart type called "Sparkline" and the jsFiddle example shows a way that the rendering can be delayed using a setTimout with it then rendering them in "chunks".

For me to make this work the way that I would need, I would have to remove all of the data from the script (or at least anything being populated from item.) and instead add 7+ data attributes onto each of the HTML containers and use jQuery to get those data attributes to populate the chart data. I'm not really excited about this approach as it could make troubleshooting a bit of a nightmare.

Does anyone know if it is possible to add each of the charts being rendered into some kind of queue so that they get rendered 1 at a time instead of the browser doing them all at the same time?

3
  • Maybe better is load chart in visible part of page and then catch scroll event and load other ? Commented Apr 1, 2015 at 14:06
  • thanks @SebastianBochan , I was considering some kind of "lazyload". I was really hoping that there may be some way that I could do this without having to add extra markup (which is usually a requirement for lazloading).. Commented Apr 1, 2015 at 14:24
  • But you have just given me an idea! I'm going to try and create each chart as a var/function and then call each chart to render using a timer... Commented Apr 1, 2015 at 14:25

1 Answer 1

1

This is how I did it:

<script> 
var chartFunctions = [];
@foreach (var item in Model.ChartRows.Where(m => !m.SummaryRow))
{ 
    var chart_@(item.ID) = function () {
        $('#container_@(item.ID)').highcharts({ 
             //code removed for brevity
        });
    }
    //add this function into the array
    chartFunctions.push(chart_@(item.ID));  
}


    function renderCharts() {
        var time = +new Date(),
            len = chartFunctions.length; 

        for (i = 0; i < len; i += 1) {

            //call each function in the function array
            chartFunctions[i]();

            // If the process takes too much time
            if (new Date() - time > 500) { 
                chartFunctions.splice(0, i + 1);
                setTimeout(renderCharts, 0);
                break;
            }
        }
    }

    renderCharts();
</script> 

And I also needed to use a foreach to match up the chartID and the containerID:

@foreach (var item in Model.ChartRows.Where(m => !m.SummaryRow))
{ 
    <div id="container_@(item.ID)"></div><br />
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.