简体   繁体   中英

Create an array of C# objects dynamically in javascript (using ChartJs)

I am trying to create a chart (using CharJs.js) with multiple data sets and have it displayed in my MVC project. The idea is to not have the datasets manually predefined and then access each one of it in my view. This has to be built dynamically based on how many objects I have in a list.

This is my Model:

 [DataContract]
public class DataPoint : IDataPoint
{
    public DataPoint(string label, double y)
    {
        this.Label = label;
        this.Y = y;
    }

    //Explicitly setting the name to be used while serializing to JSON.
    [DataMember(Name = "label")]
    public string Label { get; set; }

    //Explicitly setting the name to be used while serializing to JSON.
    [DataMember(Name = "y")]
    public Nullable<double> Y { get; set; }
    //public List<double> Y { get; set; }
}

My Controller:

        public async Task<ActionResult> ShowDetails(int ProductId, string PartId, string SupplierName, string fromSearchString, int? fromPage)
    {
        List<string> DbSupplierList = await _itScopeRepository.GetSupplierByPartId(Convert.ToInt32(PartId));

        var ItScopeProduct = _itScopeRepository.GetProductById(ProductId);
        ItScopeProduct.Supplier = SupplierName;
        ItScopeProduct.SupplierList = DbSupplierList;

        ViewBag.FromSearchString = fromSearchString;
        ViewBag.FromPage = fromPage;

        var obj = await CreateLineChart(DbSupplierList, PartId);         

        ItScopeProduct.DataPoints = obj;

        return View("DetailsView", ItScopeProduct);
    }

In my case here, the DataPoints is of type List<List<DataPoint>> and the list is being unfold in my View:

And this is my view:

 <!DOCTYPE HTML>
<html>
    <head>
        <script src="~/Scripts/jquery-1.7.1.js"></script>
        <script type="text/javascript">

            window.onload = function () {

                var dataSecond = {
                    type: "line",
                    name:'@Html.Raw(JsonConvert.SerializeObject(Model.Supplier))',
                    showInLegend: true,
                    dataPoints: @Html.Raw(JsonConvert.SerializeObject(Model.DataPoints[0]))
                };

                var dataSecond2 = {
                    type: "line",
                    name:"Dexxit",
                    showInLegend: true,
                    dataPoints: @Html.Raw(JsonConvert.SerializeObject(Model.DataPoints[1]))
                };

            var chart = new CanvasJS.Chart("chartContainer", {
                animationEnabled: true,
                title: {
                    text: "Product price history"
                },
                axisY: {
                    includeZero: false
                },
                toolTip: {
                    shared: true
                },

                data: [dataSecond, dataSecond2]
            });

            chart.render();

            }
        </script>
    </head>
    <body>
        <div id="chartContainer" style="height: 370px; width: 100%;"></div>
        <script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
    </body>
</html>

As you can see, right now I am taking each Object from the list manually and I would like to have it integrated in a loop where it creates an array of objects which will then be passed to my chart dataset.

I have tried something like this:

var testing;
var listOfDataPoints = [];

for(var i = 0; i < @Model.DataPoints.Count; i++){
                    testing = {
                        type: "line",
                        name: '@Html.Raw(JsonConvert.SerializeObject(Model.Supplier))',
                        showInLegend: true,
                        dataPoints: @Html.Raw(JsonConvert.SerializeObject(Model.DataPoints[i]))
                        };

                    listOfDataPoints.push(testing);
                }

But unfortunately I cannot pass a javascript int value to my C# model, therefore making this solution unusable.

Now my question is: Is it possible to loop through my List of objects and create n amount (base on how many items are in my list)of javascript objects and have them inserted into an array?

The js obj should have the following structure:

var myDataset = {
    type: "line",
    name: '@Html.Raw(JsonConvert.SerializeObject(Model.Supplier))',
    showInLegend: true,
    dataPoints: @Html.Raw(JsonConvert.SerializeObject(Model.DataPoints[i]))
}

Ps. I am not very experienced with javascript, reason for why I am reaching for some guidance since I haven't found anything similar to what I need.

EDIT

I have tried the other way around: Having ac# loop and execute a javascript function where i am creating my objects.

                    var yest = [];
                    var listOfPoints = [];

                function addMarker(supplier, datapo)
                {
                    yest = {
                        type: "line",
                        name: "Dexxit",
                        showInLegend: true,
                        dataPoints: datapo
                    };
                    listOfPoints.push(yest);
                }

                @for(int i = 0; i < Model.DataPoints.Count; i++)
                {
                    @:addMarker('@Html.Raw(JsonConvert.SerializeObject(Model.Supplier))', @Html.Raw(JsonConvert.SerializeObject(Model.DataPoints[i])));
                }

But when i am assigning listOfPoints to my dataset, it shows an empty chart. Any ideas why?

Manage to find a working solution based on my last edit: Had some small changes on my Controller and that was to change one of my Model (the one passed to my View) functions from List<List<DataPoint>> DataPoints {get;set;} to `List>> DataPoint{get;set;}

My new Controller:

        public async Task<ActionResult> ShowDetails(int ProductId, string PartId, string SupplierName, string fromSearchString, int? fromPage)
    {
        List<string> DbSupplierList = await _itScopeRepository.GetSupplierByPartId(Convert.ToInt32(PartId));

        var ItScopeProduct = _itScopeRepository.GetProductById(ProductId);
        ItScopeProduct.Supplier = SupplierName;
        ItScopeProduct.SupplierList = DbSupplierList;

        ViewBag.FromSearchString = fromSearchString;
        ViewBag.FromPage = fromPage;

        var obj = await CreateLineChart(DbSupplierList, PartId);

        List<KeyValuePair<string, List<IDataPoint>>> ConvertToInterface = new List<KeyValuePair<string, List<IDataPoint>>>();

        foreach (var item in obj)
        {
            ConvertToInterface.Add(new KeyValuePair<string, List<IDataPoint>>(item.Key, item.Value.ToList<IDataPoint>()));
        }

        ItScopeProduct.DataPoints = ConvertToInterface;

        return View("DetailsView", ItScopeProduct);
    }

Updated View:

<!DOCTYPE HTML>
<html>
    <head>
        <script src="~/Scripts/jquery-1.7.1.js"></script>
        <script type="text/javascript">

            window.onload = function () {

                var listOfDataPoints = [];
                var MyObj;

                function addMarker(supplier, datapo)
                {
                    var yest = {
                            type: "line",
                            name: supplier,
                            showInLegend: true,
                            dataPoints: datapo
                        };

                    return yest;
                }

                @for(int i = 0; i < Model.DataPoints.Count; i++)
                {
                    @:MyObj = addMarker('@Html.Raw(JsonConvert.SerializeObject(Model.DataPoints[i].Key))', @Html.Raw(JsonConvert.SerializeObject(Model.DataPoints[i].Value)));
                    @:listOfDataPoints.push(MyObj);
                }

            var chart = new CanvasJS.Chart("chartContainer", {
                animationEnabled: true,
                title: {
                    text: "Product price history"
                },
                axisY: {
                    includeZero: false
                },
                toolTip: {
                    shared: true
                },

                data: listOfDataPoints
            });

            chart.render();

            }
        </script>
    </head>
    <body>
        <div id="chartContainer" style="height: 370px; width: 100%;"></div>
        <script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
    </body>
</html>

My chart is now dynamically built and it can show data based on what is in my Model.DataPoints.

I hope this can be of some help for someone in the same position.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM