119

I'm trying to load a JavaScript array with an array from my model. Its seems to me that this should be possible.

Neither of the below ways work.

Cannot create a JavaScript loop and increment through Model Array with JavaScript variable

for(var j=0; j<255; j++)
{
    jsArray = (@(Model.data[j])));
}

Cannot create a Razor loop, JavaScript is out of scope

@foreach(var d in Model.data)
{
    jsArray = d;
}

I can get it to work with

var jsdata = @Html.Raw(Json.Encode(Model.data)); 

But I don't know why I should have to use JSON.

Also while at the moment I'm restricting this to 255 bytes. In the future it could run into many MBs.

Banana
  • 2,435
  • 7
  • 34
  • 60
Tom Martin
  • 1,227
  • 2
  • 10
  • 17

12 Answers12

255

This is possible, you just need to loop through the razor collection

<script type="text/javascript">

    var myArray = [];

    @foreach (var d in Model.data)
    {
        @:myArray.push("@d");
    }

    alert(myArray);

</script>
Halo
  • 1,730
  • 1
  • 8
  • 31
heymega
  • 9,215
  • 8
  • 42
  • 61
  • Except I had to declare my array using the following notation var myArray= new Array(); – Tom Martin May 21 '14 at 11:11
  • Gald it works - Yes otherwise it will look for a C# object called myArray. – heymega May 21 '14 at 11:11
  • 2
    Big help. I thought I'd have some huge problems with building a javascript object from a model dictionary. – IAbstract Aug 11 '15 at 19:48
  • Thank you! I neeeded this, because I had to pass a List of Strings to Javascript and then to Typescript for my Angular App :) – Bluesight Feb 16 '17 at 08:17
  • @mmcrae, `@d` is declared inside the foreach loop. Notice the d has the term VAR in front. That enables it to be used _inside_ the foreach loop – JhWebDev Apr 04 '19 at 16:45
  • 1
    note that this will render invalid javascript if the items in your array contain a quote or backslash. A way to fix that, is to use : @:myArray.push("@Html.Raw(HttpUtility.JavaScriptStringEncode(d))"); – Allie May 08 '19 at 14:55
14

I was working with a list of toasts (alert messages), List<Alert> from C# and needed it as JavaScript array for Toastr in a partial view (.cshtml file). The JavaScript code below is what worked for me:

var toasts = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(alerts));
toasts.forEach(function (entry) {
    var command = entry.AlertStyle;
    var message = entry.Message;
    if (command === "danger") { command = "error"; }
    toastr[command](message);
});
Soma Mbadiwe
  • 1,594
  • 16
  • 15
8

JSON syntax is pretty much the JavaScript syntax for coding your object. Therefore, in terms of conciseness and speed, your own answer is the best bet.

I use this approach when populating dropdown lists in my KnockoutJS model. E.g.

var desktopGrpViewModel = {
    availableComputeOfferings: ko.observableArray(@Html.Raw(JsonConvert.SerializeObject(ViewBag.ComputeOfferings))),
    desktopGrpComputeOfferingSelected: ko.observable(),
};
ko.applyBindings(desktopGrpViewModel);

...

<select name="ComputeOffering" class="form-control valid" id="ComputeOffering" data-val="true" 
data-bind="options: availableComputeOffering,
           optionsText: 'Name',
           optionsValue: 'Id',
           value: desktopGrpComputeOfferingSelect,
           optionsCaption: 'Choose...'">
</select>

Note that I'm using Json.NET NuGet package for serialization and the ViewBag to pass data.

Donal Lafferty
  • 5,807
  • 7
  • 43
  • 60
6

To expand on the top-voted answer, for reference, if the you want to add more complex items to the array:

@:myArray.push(ClassMember1: "@d.ClassMember1", ClassMember2: "@d.ClassMember2");

etc.

Furthermore, if you want to pass the array as a parameter to your controller, you can stringify it first:

myArray = JSON.stringify({ 'myArray': myArray });

mcfroob
  • 1,044
  • 1
  • 11
  • 13
  • There is an issue with your code. It should be `@:myArray.push(ClassMember1: "@d.ClassMember1", ClassMember2: "@d.ClassMember2");` – Asad Apr 29 '17 at 10:45
  • It seems that now the array code should be `@:myArray.push({ClassMember1: "@d.CassMember1", ClassMember2: "@d.ClassMember2"})` . . . the { . . .} around all members is required. – Paul Gibson Jan 10 '23 at 21:43
4

I was integrating a slider and needed to get all the files in the folder and was having same situationof C# array to javascript array.This solution by @heymega worked perfectly except my javascript parser was annoyed on var use in foreach loop. So i did a little work around avoiding the loop.

var allowedExtensions = new string[] { ".jpg", ".jpeg", ".bmp", ".png", ".gif" };

var bannerImages = string.Join(",", Directory.GetFiles(Path.Combine(System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath, "Images", "banners"), "*.*", SearchOption.TopDirectoryOnly)
    .Where(d => allowedExtensions.Contains(Path.GetExtension(d).ToLower()))
    .Select(d => string.Format("'{0}'", Path.GetFileName(d)))
    .ToArray());

And the javascript code is

var imagesArray = new Array(@Html.Raw(bannerImages));

Hope it helps

Ali Umair
  • 1,386
  • 1
  • 21
  • 42
1

This would be better approach as I have implemented :)

@model ObjectUser
@using System.Web.Script.Serialization
@{ 
    var javaScriptSearilizer = new JavaScriptSerializer();
    var searializedObject = javaScriptSearilizer.Serialize(Model);
 }

<script>
    var searializedObject = @Html.Raw(searializedObject )
    console.log(searializedObject);
    alert(searializedObject);
</script>

Hope this will help you to prevent you from iterating model ( happy coding )

Muhammad Essa
  • 142
  • 1
  • 10
0

If it is a symmetrical (rectangular) array then Try pushing into a single dimension javascript array; use razor to determine the array structure; and then transform into a 2 dimensional array.

// this just sticks them all in a one dimension array of rows * cols
var myArray = new Array();
@foreach (var d in Model.ResultArray)
{
    @:myArray.push("@d");
}

var MyA = new Array();

var rows = @Model.ResultArray.GetLength(0);
var cols = @Model.ResultArray.GetLength(1);

// now convert the single dimension array to 2 dimensions
var NewRow;
var myArrayPointer = 0;

for (rr = 0; rr < rows; rr++)
{
  NewRow = new Array();
  for ( cc = 0; cc < cols; cc++)
  {
    NewRow.push(myArray[myArrayPointer]);
    myArrayPointer++;
  }
  MyA.push(NewRow);
}
John Arundell
  • 118
  • 1
  • 6
0

The valid syntax with named fields:

  var array = [];

     @foreach (var item in model.List)
     {
        @:array.push({ 
                       "Project": "@item.Project",
                       "ProjectOrgUnit": "@item.ProjectOrgUnit"
                     });
     }
Iván Kollár
  • 39
  • 1
  • 3
0
@functions
{
    string GetStringArray()
    {
        var stringArray = "[";

        for (int i = 0; i < Model.List.Count; i++)
        {
            if (i != Model.List.Count - 1)
            {
                stringArray += $"'{Model.List[i]}', ";
            }
            else
            {
                stringArray += $"'{Model.List[i]}']";
            }
        }

        return stringArray;
    }
}

<script>
    var list = @Html.Raw(GetStringArray());
</script>
Joel Wiklund
  • 1,697
  • 2
  • 18
  • 24
0

Maybe it could be interesting also this easy solution that can be easily applied also to javascript dictionaries:

<script type="text/javascript">
    var myArray = [
    @foreach (var d in Model.data)
    {
        @:"@d",
    }
    ];
</script>

that translates into this (string1 to stringN are considered here the content of Model.data)

<script type="text/javascript">
    var myArray = [
        "string1",
        "string2",
        "string3",
        ...
        "stringN",
    ];
</script>
Leonardo Daga
  • 135
  • 1
  • 12
0

I needed to create an array of JSON objects. The following method worked.

const data=
        [
            @foreach (var item in Model.Data)
            {
                @:{ items: { scores: @item.Score, link: @item.Id, color: '#58C1EE', borderColor: 'black' } },
            }
        ];
MrAlbino
  • 308
  • 2
  • 10
-1
<script>
    var tempArray = [];

    @foreach (var item in Model.Collection)
    {
        @:tempArray.push({ Field1: "@item.Field1", Field2: "@item.Field2" });
    }

    $("#btn").on("click", function () {
        $.ajax({
            url: '/controller/action',
            type: 'POST',
            contentType: 'application/json; charset=utf-8',
            data: JSON.stringify(tempArray),
            success: function (resp) {
                alert(resp);
            }
        });
    });
</script>

Controller/Action parameter: ICollection <_Model> _items