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.
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>
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);
});
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.
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 });
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
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 )
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);
}
The valid syntax with named fields:
var array = [];
#foreach (var item in model.List)
{
#:array.push({
"Project": "#item.Project",
"ProjectOrgUnit": "#item.ProjectOrgUnit"
});
}
#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>
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>
<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
Related
In c# codebehind I define a few Lists this way:
public List<string> divs = new List<string>();
public List<List<string>> names = new List<List<string>>();
public List<List<List<string>>> labels = new List<List<List<string>>>();
public List<List<List<double>>> longitude = new List<List<List<double>>>();
Quite large lists I know but I feel it's necessary for getting all my info from my source organized correctly.
in JS I serialize these like this:
var divArr = <%=new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(divs)%>;
var names = <%=new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(names)%>;
var lbl = <%=new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(labels)%>;
var long = <%=new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(longitude)%>;
And then I try to do a function to plot all this on separate graphs. 10 graphs in total on my page that can have several lines on all of them. Trying to make my page as dynamic as possible. So I have a function to loop through all of this and try to plot it all.
function doGraph(){
for(index = 0; index < divArr.length; ++index){
(function() {
var data = [];
for(indx = 0; indx < lbl[index].length; ++indx){
var trace = {
name: names[index][indx],
x: lbl[index][indx],
y: long[index][indx],
mode:'lines'
};
data.push(trace);
}
var gd = document.getElementById(divArr[index]);
plotly.newPlot(gd,data);
})();
}
}
And it ALMOST works. Every graph seems to plot the first set of data given to it but nothing afterwords. Maybe I've been staring at this too long but I just can't see what I'm doing wrong here but I'm sure it's something I've just over looked. Or maybe I'm overreaching and I can't do this sort of thing? Any insight is appreciated!
So I found out the problem was with the serialization from my lists to js arrays. Apparently js serialize can't quite handle the level of multidimensional list I was going crazy with. So I fixed it by making the lists one level less deep and made another list to keep track of how "deep" they are in this fashion:
C# Codebehind:
public List<List<string>> names = new List<List<string>>();
public List<int> numObjs = new List<int>();
public List<List<string>> labels = new List<List<string>>();
public List<List<double>> longitude = new List<List<double>>();
JS Serialization:
var divArr = <%=new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(divs)%>;
var names = <%=new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(names)%>;
var numO = <%=new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(numObjs)%>;
var lbl = <%=new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(labels)%>;
var long = <%=new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(longitude)%>;
Then the JS function has the real changes with a loop in this way:
function doGraph(){
var cur = 0;
for(var index = 0; index < divArr.length; ++index){
var data = [];
var top = cur + numO[index];
for(var indx = cur; indx < top; ++indx){
data.push({
name: names[indx],
mode:'lines',
x: lbl[indx],
y: long[indx],
});
cur++;
}
var gd = document.getElementById(divArr[index]);
Plotly.newPlot(gd, data,
layout , {scrollZoom:true,modeBarButtonsToRemove:['sendDataToCloud'],showLink:false,displaylogo:false});
}
}
Also my function within a function was definitely unnecessary as #flipperweid said.
Following is JSON notation returned by Response::json() function from Laravel:
{
"area":["zone1","zone2","zone3"],
"target":["7.91","4.95","2.95"],
"sales":["12.35","6.99","4.13"]
}
How can i get 'area' as category, target and sales as series for highcharts(column) using javascript?
For example, how can i get following:
var cat=['zone1','zone2', 'zone3'];
var series1=[7.91, 4.95,2.95];
var series2=[12.35,6.99,4.13];
There are a few ways you can do this. If you are using pure javascript you can do something like
cat = new Array();
series1 = new Array();
series2 = new Array();
for (var value in data["area"])
{
cat.push(data["area"][value]);
}
for (var value in data["target"])
{
series1.push(data["target"][value]);
}
for (var value in data["sales"])
{
series2.push(data["sales"][value]);
}
Or if you want a solution using jQuery then you can do something like:
var cat = $.map(data["area"], function(value,key) { return value; });
var series1 = $.map(data["target"], function(value,key) { return value; });
var series2 = $.map(data["sales"], function(value,key) { return value; });
Both solutions will give you an output of:
["zone1", "zone2", "zone3"]
["7.91", "4.95", "2.95"]
["12.35", "6.99", "4.13"]
Edit
So the data I used was the same JSON object that you provided where every value is a string, but your desired output (and the output Highcharts will want) is the series data in Numeric form so you will need to take that into account.
I guess it can help you.
var data = {
"area":["zone1","zone2","zone3"],
"target":["7.91","4.95","2.95"],
"sales":["12.35","6.99","4.13"]
};
var cat = data.area;
var series1 = data.target;
var series2 = data.sales;
I have a string that looks like:
<tr><td>Date</td><td>Value</td></tr>
<tr><td>2013-01-01</td><td>231.198</td></tr>
<tr><td>2013-02-01</td><td>232.770</td></tr>
<tr><td>2013-03-01</td><td>232.340</td></tr>
<tr><td>2013-04-01</td><td>231.485</td></tr>
<tr><td>2013-05-01</td><td>231.831</td></tr>
<tr><td>2013-06-01</td><td>232.944</td></tr>
<tr><td>2013-07-01</td><td>233.318</td></tr>
...which is of course essentially a table.
I'd like to dynamically convert this string into an array containing 2 arrays. One of dates, one of values.
[Edited in]
An array of objects with date and values would work too.
The following::
var input = // your string
var output = $(input).slice(1).map(function(i,el) {
var tds = $(el).find("td");
return { "date" : tds.eq(0).text(), "value" : tds.eq(1).text() };
}).get();
...will return an array of objects in this format:
[{"date":"2013-01-01","value":"231.198"}, {"date":"2013-02-01","value":"232.770"}, ... ]
If you'd like each value to be treated as a number you can convert it like so:
return { "date" : tds.eq(0).text(), "value" : +tds.eq(1).text() };
// add the unary plus operator ---------------^
Then the result will be:
[{"date":"2013-01-01","value":231.198}, {"date":"2013-02-01","value":232.77}, ... ]
While you've already accepted an answer, I thought I'd post a plain JavaScript solution (albeit largely because I spent time working on it, before Barmar pointed out that you're willing and able to use jQuery):
function cellContents(htmlStr, what) {
var _table = document.createElement('table');
_table.innerHTML = htmlStr;
var rows = _table.getElementsByTagName('tr'),
text = 'textContent' in document ? 'textContent' : 'innerText',
cells,
matches = {};
for (var w = 0, wL = what.length; w < wL; w++) {
matches[what[w]] = [];
for (var r = 1, rL = rows.length; r < rL; r++) {
cells = rows[r].getElementsByTagName('td');
matches[what[w]].push(cells[w][text]);
}
}
return matches;
}
var str = "<tr><td>Date</td><td>Value</td></tr><tr><td>2013-01-01</td><td>231.198</td></tr><tr><td>2013-02-01</td><td>232.770</td></tr><tr><td>2013-03-01</td><td>232.340</td></tr><tr><td>2013-04-01</td><td>231.485</td></tr><tr><td>2013-05-01</td><td>231.831</td></tr><tr><td>2013-06-01</td><td>232.944</td></tr><tr><td>2013-07-01</td><td>233.318</td></tr>";
console.log(cellContents(str, ['dates', 'values']));
JS Fiddle demo.
For a pure JavaScript solution you can try something like this (assuming str holds your string) :
var arrStr = str.replace(/<td>/g, "").replace(/<tr>/g, "").split("</td></tr>");
var arrObj = [];
var arrData
for (var i = 1; i < arrStr.length - 1; i++) {
arrData = arrStr[i].split("</td>");
arrObj.push({ Date: arrData[0], Value: arrData[1] })
}
It's a burte-force string replacement/split, but at the end arrObj will have array of objects.
if its a valid html table structure, wrap it between table tags, and use jquery to parse it.
then use jquery's selectors to find the columns.
e.g something like this ( pseudo code, havent tried it )
table = $(yourTableString);
dates = table.find("tr td:nth-child(1)");
values = table.find("tr td:nth-child(2)");
Using jQuery:
var table = $('<table>'+str+'</table>');
var result = {};
table.find('tr:gt(0)').each(function () {
var date = $(this).find("td:nth-child(1)").text();
var value = $(this).find("td:nth-child(2)").text();
result[date] = value;
}
:gt(0) is to skip over the header line. This will create an associative array object that maps dates to values. Assuming the dates are unique, this is likely to be more useful than two arrays or an array of objects.
I have an array that is passed through the ViewData to my view. This array is composed of several elements of one of my Models.
I want to iterate through these elements and use javascript code with elements of the object.
Example in pseudo-code:
for x in ViewData["asdasd"] {
foo(x.Property)
}
foo is a javascript function.
How can i do this?
Use reflection to get the value. (edited because I realized I totally misunderstood the question at first)
#{
Type t = typeof(MyModelType);
foreach (string x in ViewData["mykey"])
{
var propertyVal = t.GetProperty(x).GetValue(MyModelObject, null);
#Html.Raw("foo('" + propertyVal + "')");
}
}
If I am correct try:
var myArray = new Array();
myArray = <%= ViewData[yourarray] %>;
for (var i = 0; i < myArray.length; i++) {
foo(myArray[i]);
//Do something
}
You could use something like this:
#{
foreach (var firstName in (ViewData["my_list"] as IEnumerable<string>)) {
#Html.Raw(firstName);<br />
}
}
in my app i need to send an javascript Array object to php script via ajax post. Something like this:
var saveData = Array();
saveData["a"] = 2;
saveData["c"] = 1;
alert(saveData);
$.ajax({
type: "POST",
url: "salvaPreventivo.php",
data:saveData,
async:true
});
Array's indexes are strings and not int, so for this reason something like saveData.join('&') doesn't work.
Ideas?
Thanks in advance
Don't make it an Array if it is not an Array, make it an object:
var saveData = {};
saveData.a = 2;
saveData.c = 1;
// equivalent to...
var saveData = {a: 2, c: 1}
// equivalent to....
var saveData = {};
saveData['a'] = 2;
saveData['c'] = 1;
Doing it the way you are doing it with Arrays is just taking advantage of Javascript's treatment of Arrays and not really the right way of doing it.
If the array is already defined, you can create a json object by looping through the elements of the array which you can then post to the server, but if you are creating the array as for the case above, just create a json object instead as sugested by Paolo Bergantino
var saveData = Array();
saveData["a"] = 2;
saveData["c"] = 1;
//creating a json object
var jObject={};
for(i in saveData)
{
jObject[i] = saveData[i];
}
//Stringify this object and send it to the server
jObject= YAHOO.lang.JSON.stringify(jObject);
$.ajax({
type:'post',
cache:false,
url:"salvaPreventivo.php",
data:{jObject: jObject}
});
// reading the data at the server
<?php
$data = json_decode($_POST['jObject'], true);
print_r($data);
?>
//for jObject= YAHOO.lang.JSON.stringify(jObject); to work,
//include the follwing files
//<!-- Dependencies -->
//<script src="http://yui.yahooapis.com/2.9.0/build/yahoo/yahoo-min.js"></script>
//<!-- Source file -->
//<script src="http://yui.yahooapis.com/2.9.0/build/json/json-min.js"></script>
Hope this helps
You can iterate the key/value pairs of the saveData object to build an array of the pairs, then use join("&") on the resulting array:
var a = [];
for (key in saveData) {
a.push(key+"="+saveData[key]);
}
var serialized = a.join("&") // a=2&c=1
There is actuly a difference between array object and JSON object. Instead of creating array object and converting it into a json object(with JSON.stringify(arr)) you can do this:
var sels = //Here is your array of SELECTs
var json = { };
for(var i = 0, l = sels.length; i < l; i++) {
json[sels[i].id] = sels[i].value;
}
There is no need of converting it into JSON because its already a json object.
To view the same use json.toSource();
When using the data on the server, your characters can reach with the addition of slashes eg
if string = {"hello"}
comes as string = {\ "hello \"}
to solve the following function can be used later to use json decode.
<?php
function stripslashes_deep($value)
{
$value = is_array($value) ?
array_map('stripslashes_deep', $value) :
stripslashes($value);
return $value;
}
$array = $_POST['jObject'];
$array = stripslashes_deep($array);
$data = json_decode($array, true);
print_r($data);
?>