最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

asp.net mvc - Populating javascript chart with Razor model data - Stack Overflow

programmeradmin3浏览0评论

I have a line chart I want to populate with data from a viewmodel in MVC6/Razor

My Viewmodels are

public class LeaderboardViewModel
{
    public List<LeaderboardViewEntry> LeaderboardViewEntries { get; set; }
    public HistoicPointsViewModel HistoicPoints { get; set; } 
}

public class HistoicPointsViewModel
{
    public HistoicPointsViewModel()
    {
        PlayerHistores = new List<PlayerHistoricViewModel>();
    }

    public DateTime[] YAxisDates { get; set; }
    public List<PlayerHistoricViewModel> PlayerHistores { get; set; } 
}

public class PlayerHistoricViewModel
{
    public PlayerHistoricViewModel()
    {
        Points = new List<int?>();
    }

    public string PlayerName { get; set; }
    public List<int?> Points { get; set; }
}

And my view is script section in my View is:

@model Foosball9001.ViewModels.Leaderboards.LeaderboardViewModel

<canvas id="myChart" width="800" height="400"></canvas>
@section Scripts{
<script type="text/javascript">
    var data = {
        labels: @Model.HistoicPoints.YAxisDates,
        datasets: [
            {
                @foreach (PlayerHistoricViewModel x in Model.HistoicPoints.PlayerHistores)
                {
                    {
                        label: x.PlayerName,
                        fillColor: "rgba(220,220,220,0.2)",
                        strokeColor: "rgba(220,220,220,1)",
                        pointColor: "rgba(220,220,220,1)",
                        pointStrokeColor: "#fff",
                        pointHighlightFill: "#fff",
                        pointHighlightStroke: "rgba(220,220,220,1)",
                        data: x.Points
                    }
                }

            }
        ]
    };

    var ctx = document.getElementById("myChart").getContext("2d");
    var myNewChart = new Chart(ctx).Line(data);
</script>
}

So I want to use my HistoicPointsViewModel.YAxisDates as the Y axis coordinates and then I want to create a dataset for each player in my PlayerHistores where it takes the data from PlayerHistoricViewModel.Points as the data to plot into the graph

My problem is writing the dynamic javascript using Razor so it looks like the example

var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
    {
        label: "My First dataset",
        fillColor: "rgba(220,220,220,0.2)",
        strokeColor: "rgba(220,220,220,1)",
        pointColor: "rgba(220,220,220,1)",
        pointStrokeColor: "#fff",
        pointHighlightFill: "#fff",
        pointHighlightStroke: "rgba(220,220,220,1)",
        data: [65, 59, 80, 81, 56, 55, 40]
    },
    {
        label: "My Second dataset",
        fillColor: "rgba(151,187,205,0.2)",
        strokeColor: "rgba(151,187,205,1)",
        pointColor: "rgba(151,187,205,1)",
        pointStrokeColor: "#fff",
        pointHighlightFill: "#fff",
        pointHighlightStroke: "rgba(151,187,205,1)",
        data: [28, 48, 40, 19, 86, 27, 90]
    }
]
};

I have a line chart http://www.chartjs/docs/#line-chart-introduction I want to populate with data from a viewmodel in MVC6/Razor

My Viewmodels are

public class LeaderboardViewModel
{
    public List<LeaderboardViewEntry> LeaderboardViewEntries { get; set; }
    public HistoicPointsViewModel HistoicPoints { get; set; } 
}

public class HistoicPointsViewModel
{
    public HistoicPointsViewModel()
    {
        PlayerHistores = new List<PlayerHistoricViewModel>();
    }

    public DateTime[] YAxisDates { get; set; }
    public List<PlayerHistoricViewModel> PlayerHistores { get; set; } 
}

public class PlayerHistoricViewModel
{
    public PlayerHistoricViewModel()
    {
        Points = new List<int?>();
    }

    public string PlayerName { get; set; }
    public List<int?> Points { get; set; }
}

And my view is script section in my View is:

@model Foosball9001.ViewModels.Leaderboards.LeaderboardViewModel

<canvas id="myChart" width="800" height="400"></canvas>
@section Scripts{
<script type="text/javascript">
    var data = {
        labels: @Model.HistoicPoints.YAxisDates,
        datasets: [
            {
                @foreach (PlayerHistoricViewModel x in Model.HistoicPoints.PlayerHistores)
                {
                    {
                        label: x.PlayerName,
                        fillColor: "rgba(220,220,220,0.2)",
                        strokeColor: "rgba(220,220,220,1)",
                        pointColor: "rgba(220,220,220,1)",
                        pointStrokeColor: "#fff",
                        pointHighlightFill: "#fff",
                        pointHighlightStroke: "rgba(220,220,220,1)",
                        data: x.Points
                    }
                }

            }
        ]
    };

    var ctx = document.getElementById("myChart").getContext("2d");
    var myNewChart = new Chart(ctx).Line(data);
</script>
}

So I want to use my HistoicPointsViewModel.YAxisDates as the Y axis coordinates and then I want to create a dataset for each player in my PlayerHistores where it takes the data from PlayerHistoricViewModel.Points as the data to plot into the graph

My problem is writing the dynamic javascript using Razor so it looks like the example

var data = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
    {
        label: "My First dataset",
        fillColor: "rgba(220,220,220,0.2)",
        strokeColor: "rgba(220,220,220,1)",
        pointColor: "rgba(220,220,220,1)",
        pointStrokeColor: "#fff",
        pointHighlightFill: "#fff",
        pointHighlightStroke: "rgba(220,220,220,1)",
        data: [65, 59, 80, 81, 56, 55, 40]
    },
    {
        label: "My Second dataset",
        fillColor: "rgba(151,187,205,0.2)",
        strokeColor: "rgba(151,187,205,1)",
        pointColor: "rgba(151,187,205,1)",
        pointStrokeColor: "#fff",
        pointHighlightFill: "#fff",
        pointHighlightStroke: "rgba(151,187,205,1)",
        data: [28, 48, 40, 19, 86, 27, 90]
    }
]
};
Share Improve this question edited Sep 13, 2018 at 11:53 Svenmarim 3,7356 gold badges26 silver badges58 bronze badges asked Dec 17, 2015 at 19:57 Mech0zMech0z 3,6476 gold badges51 silver badges87 bronze badges 2
  • 1 If this is asp MVC 6, why do you have an asp MVC 4 tag? By the way, what's the model in your view? – ataravati Commented Dec 17, 2015 at 20:21
  • @ataravati Sorry cleaned it up, added the Viewmodel to the view and added the viewmodel to the classes – Mech0z Commented Dec 17, 2015 at 20:43
Add a ment  | 

3 Answers 3

Reset to default 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

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.

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'
};
发布评论

评论列表(0)

  1. 暂无评论