[Chartjs]-Populating javascript chart with Razor model data

4๐Ÿ‘

โœ…

I think the easiest way would be to create corresponding ChartModel that could be serialized to the exact JSON structure that you need:

public class DtatsetModel
{
    public string label {get;set;}
    public const string fillColor = "rgba(220,220,220,0.2)";
    public const string strokeColor = "rgba(220,220,220,1)";
    public const string pointColor = "rgba(220,220,220,1)";
    public const string pointStrokeColor = "#fff";
    public const string pointHighlightFill = "#fff";
    public const string pointHighlightStroke = "rgba(151,187,205,1)";
    public List<string> data {get;set;}

    public DtatsetModel(PlayerHistoricViewModel x)
    {
        this.label = x.PlayerName;
        this.data =  x.Points.Where(p=>p.HasValue).Select(p=>p.ToString());
    }
}

public class ChartModel
{
   public List<string> labels {get;set;}
   public List<DtatsetModel> datasets {get;set;}

   public ChartModel(HistoicPointsViewModel x)
   {
      this.labels = x.Select(d=>d.ToString("MMMM"));
      this.datasets = x.PlayerHistores.Select(h=>new DtatsetModel(h));
   }
}

then in the view you can do something like

<script type="text/javascript">
    var data = @Html.Raw(JsonConvert.SerializeObject(new ChartModel(Model.HistoicPoints)))
    var ctx = document.getElementById("myChart").getContext("2d");
    var myNewChart = new Chart(ctx).Line(data);
</script>

For serialization I used JSON.NET

1๐Ÿ‘

you need to encode the model list to a json you can do this using the json helper from razor, try this:

var datelist = @Html.Raw(Json.Encode(Model.HistoicPoints.YAxisDates.Select(v => v.ToString("MMMM")));

ToString("MMMM") will give you the entire month name.

the same for the player historic

var playerHistory = @Html.Raw(Json.Encode(Model.HistoicPoints.PlayerHistores.Select(v => new
{
    label = v.PlayerName,
    fillColor = String.Format("rgba({0},{1},{2},{3})", Color.Blue.R, Color.AliceBlue.G, Color.AliceBlue.B, Color.AliceBlue.A),
    strokeColor = String.Format("rgba({0},{1},{2},{3})", Color.Blue.R, Color.AliceBlue.G, Color.AliceBlue.B, Color.AliceBlue.A),
    pointColor = String.Format("rgba({0},{1},{2},{3})", Color.Blue.R, Color.AliceBlue.G, Color.AliceBlue.B, Color.AliceBlue.A),
    pointStrokeColor = "#fff",
    pointHighlightFill = "#fff",
    pointHighlightStroke = "rgba(220,220,220,1)",
    data = v.Points
})));

Iโ€™ve created the colors using the Color class if you want to use it or just set the rgba as a string.

and basically you do this in the javascript code.

var data = {
    labels: '@datelist',
    datasets: '@playerHistory'
};

1๐Ÿ‘

First of all I would propose not mixing javascript and razor since inline javascript is prone for XSS.

I would make use of data attributes on some invisible elements that you can create in razor and then read those data attributes from javascript.

So just create divs with data attributes (data attributes description)

            @foreach (PlayerHistoricViewModel x in Model.HistoicPoints.PlayerHistores)
            {
                <div
                    class="players"
                    data-label= "x.PlayerName",
                    data-fillColor= "rgba(220,220,220,0.2)",
                    data-strokeColor= "rgba(220,220,220,1)",
                    data-pointColor= "rgba(220,220,220,1)",
                    data-pointStrokeColor= "#fff",
                    data-pointHighlightFill= "#fff",
                    data-pointHighlightStroke= "rgba(220,220,220,1)",
                    data-points= "x.Points"//this will maybe need some work to make json array
                />
            }

And in javascript:

var datasets = [];
$("div.players").each(function(){
    var testdata = {
              label = $(this).data('label');
              fillColor = $(this).data('label');
              ...
              points = $(this).data('points');
              //if datapoints will be json array then it will be automatically parsed as such
     }

    datasets.push(testdata);
});

This way you have decoupled javascript from razor.

Leave a comment