Reputation: 145
I'm running a bit of javascript code in a loop, creating a chart (using google visualization). After all this code is run, I need to access these objects somewhere else. My problem is that I can't just call "chart" again, since it now has been over-written.
I've managed to figure out a really hacky solution which involves using the MVC @ thing to dynamically generate something at run-time, which I then force as a variable name. It works, but I don't think it's the right way to approach this problem. Is there a way for me to dynamically change the name of the variable each time it's run?
The following code is run multiple times.
@{
var myChart = "cData" + Model.ChartId.ToString();
}
...
function () {
@myChart = new google visualization.ChartWrapper({ ... });
dashboard.bind(slider, @myChart);
dashboard.draw(data);
}
myChart changes every single time the code is run, giving me a really hacky string. By putting it without the ' marks, it becomes a variable at runtime. After all that is run, I have a resize function which run the following:
@myChart .setOption('width', width);
@myChart .setOption('height', height);
@myChart .draw();
This is also super hacky. I took advantage of how javascript ignores spaces, so that I can treat @myChart like an object.
The result is riddled with syntax errors, but it still runs, and it runs with intended results. So my question is if there is a "proper" solution for this, instead of making separate javascript functions for each individual chart I need to make.
Thanks.
Upvotes: 3
Views: 1319
Reputation: 54359
There's nothing wrong with what you've done, but it could be better.
First, you don't have to rely on a space to mix JavaScript and Razor.
@(myChart).setOption('width', width);
But that's still ugly.
<script>
// global (usual caveats about globals apply)
var charts = {};
</script>
@for( int i = 0; i < 10; i++ )
{
string chartId = "chart-" + i;
<script>
charts['@chartId'] = new Chart();
charts['@chartId'].setOption('width', width);
charts['@chartId'].setOption('height', height);
charts['@chartId'].draw();
</script>
}
<script>
function doResize(chart) {
chart.setOption('width', width);
chart.setOption('height', height);
chart.draw();
}
</script>
@for( int i = 0; i < 10; i++ )
{
<script>
(function () {
// limit the scope of the "chart" variable
var chart = new Chart();
// perform other init
// listen for resize in some manner
$(window).on("resize", function() {
doResize(chart);
});
})();
</script>
}
Approach #2 is my preferred method as it manages scope and is clear to read.
Upvotes: 3