Search code examples
javascriptc#amchartsgauge

Unable to pass value from C# to amcharts JavaScript function


I created a chart with the help of amCharts that shows temperature from the examples on their site. The chart displayed correctly.

Now I am getting the temperature from a database with C# and I am trying to pass the value to the function where temperature was hard coded, so I get dynamic values. However, I just get the chart and the needle is still at 0 and does not show the temperature.

I have tried 3 ways so far:

  1. I used a hidden field, assigned the value to hidden field in C# and called the JavaScript function showing the charts. It only shows chart. The needle does not change.
  2. I used script manager and Web API, (I don't know Web API and just used code on the Internet), it is the same result however the function in c# keeps on being continuously called.

  3. I put the entire amCharts code in a JavaScript function . I got values in c# and then used

    String script = "window.onload = function() { UpdateTemp('" + dt.Rows[0][0].ToString()+ "'); };";
    ClientScript.RegisterStartupScript(this.GetType(), "UpdateTemp", script, true);
    

    which again shows same result, map is shown needle stays on 0.

This is my code for the 3rd approach:

ASPX page, JavaScript function

<script>
 function UpdateTemp(temp) {

     am4core.ready(function() {

            // Themes begin
            am4core.useTheme(am4themes_animated);
            // Themes end

            // create chart
            var chart = am4core.create("chartdiv", am4charts.GaugeChart);
            chart.hiddenState.properties.opacity = 0; // this makes initial fade in effect

            chart.innerRadius = -25;

            var axis = chart.xAxes.push(new am4charts.ValueAxis());
            axis.min = 0;
            axis.max = 100;
            axis.strictMinMax = true;
            axis.renderer.grid.template.stroke = new am4core.InterfaceColorSet().getFor("background");
            axis.renderer.grid.template.strokeOpacity = 0.3;

            var colorSet = new am4core.ColorSet();

            var range0 = axis.axisRanges.create();
            range0.value = 0;
            range0.endValue = 50;
            range0.axisFill.fillOpacity = 1;
            range0.axisFill.fill = colorSet.getIndex(0);
            range0.axisFill.zIndex = - 1;

            var range1 = axis.axisRanges.create();
            range1.value = 50;
            range1.endValue = 80;
            range1.axisFill.fillOpacity = 1;
            range1.axisFill.fill = colorSet.getIndex(2);
            range1.axisFill.zIndex = -1;

            var range2 = axis.axisRanges.create();
            range2.value = 80;
            range2.endValue = 100;
            range2.axisFill.fillOpacity = 1;
            range2.axisFill.fill = colorSet.getIndex(4);
            range2.axisFill.zIndex = -1;

            var hand = chart.hands.push(new am4charts.ClockHand());

            // using chart.setTimeout method as the timeout will be disposed together with a chart

            chart.setTimeout(randomValue, 2000);

            function randomValue(temp) {
                hand.showValue(temp, 1000, am4core.ease.cubicOut);
                chart.setTimeout(randomValue, 2000);
            }



        }); // end am4core.ready()

    };
</script>

C# function to get temperature and call JavaScript function

public void BindGrid(String charttype)
{

    string constring = "Data Source=********.DOMAIN.ORG01;Initial Catalog=Temperature;Integrated Security=SSPI;";
    using (SqlConnection con = new SqlConnection(constring))
    {
        using (SqlCommand cmd = new SqlCommand("SELECT Temperature,HighestPoint,LowestPoint FROM Temperature", con))
        {
            cmd.CommandType = CommandType.Text;
            con.Open();
            DataTable dt = new DataTable();
            dt.Load(cmd.ExecuteReader());
            temp1.Value = dt.Rows[0][0].ToString();
            con.Close();
            String script = "window.onload = function() { UpdateTemp('" + dt.Rows[0][0].ToString()+ "'); };";
             ClientScript.RegisterStartupScript(this.GetType(), "UpdateTemp", script, true);

        }
    }
}

enter image description here


Solution

  • The quality code should be revised but I managed to make it work. I made 2 changes:

    • 1 : I used the method "PageLoad" instead of "BindGrid" (do you really need this one ?)
    • 2 : I filled the raw temperature value directly as a parameter (as it is a float on my side), you englobed your datarow value with simple quote, that's interpreted as string by javascript and the method "showValue" from "hand" seems to not tolerate it.

    Code: enter image description here

    Result:

    enter image description here

    Some ideas to improve your code:

    • Put your connection string in configuration file (never in code !)
    • If you use the "using" do not matter calling the method "close" of your resource, it's automatically called by it. (behind the using it's in fact a try-catch-finally, the close is called anyway in the finally ;) )
    • If possible separate the data access from the rendering page, create a separate class that manages it, it will improve readability and evolution of your code.
    • If the variable "temp1" is not used, just remove it.
    • When you get a data (no matter the source, could be a webservice or database or else), check always if it's null before access it and log it, it doesn't cost a lot and you avoid escalation of exceptions.
    • We are in 2019, you could use Dapper to get directly object as result from your queries instead of a generic datarow. (check the website if interested they have a lot of interesting tutorials).

    Kr, Ali