3

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.

1
  • 1
    Could you put each of your charts in an array then go through the array? Or you could create a closure for each, so the variable wouldn't get overridden. Commented Apr 21, 2016 at 21:48

1 Answer 1

3

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.

Approach 1

<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>
}

Approach 2

<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.

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.