Pass Dictionary<String,List<String>> to java script - javascript

I would like to pass a Dictionary> to client using JavaScript.
I did look at this post and I didn't understand exactly how to proceed.
In case I'm doing something wrong I'll explain what I want to do.
The dictionary contains the 'name' key of all worksheets in the Excel file, and the 'value' is the column value of the first row in that worksheet.
The UI of the client should have two "drop list", the first will contain the key which is all the names of the worksheet in the Excel file.
The second contain all the column value of the first row of the worksheets that will choose in the first drop list – which is actually a List as the value in the dictionary.
So all the back end C# code is working fine. Now I need help in the front end JavaScript.
How do I parse the data to a key value so I can do a "search" on the keys as the client chooses some "key" in the first drop list so I can get back the relevant values as a list?
Thanx!
var ajaxRequest = $.ajax({
type: "POST",
url: "http://localhost:1894/api/Values",
contentType: false,
processData: false,
data: data,
success: function(dataTest) {
}
});
This is the JSON that I get back from the server:
{"First":["Name","Link","User","Pass"],"Sec":["test01"]}
How would I perform a search on this like in C#? I want to be able to do something like this: "dict.TryGetValue(key, out value); and the out value would return as an array of string or as a List.

Try this(you don't need var ajaxRequest variable you can directly call like this:
$.ajax({
type: "POST",
url: "http://localhost:1894/api/Values",
dataType: "json",
data: data,
success: function(dataTest) {
//dataTest should contain your data in a javascript object
for(var i = 0; i < dataTest.First.length; i++)
{
window.alert("" + dataTest.First[i]);
}
for(var i = 0; i < dataTest.Sec.length; i++)
{
window.alert("" + dataTest.Sec[i]);
}
//etc...
//this should print the values returned if you showed me exactly how your JSON is...
}
});
The javascript object will contain properties with an array as the value for each property. Think of it like a map of <String, String[]>. So your returned object dataTest will have properties First and Sec and for First the value associated with the key First will be ["Name","Link","User","Pass"] which is just an array. Same for Sec. So `dataTest.First[0] will equal "Name" and dataTest.First[1] will equal "Link" etc...
*****************************************UPDATE**************************************
You can save your dataTest to a global variable in this example (myObject) then you can access like this:
var key = "First";
// Or if you want to get your key from a dropdown (select) element then you could do like this:
var key = document.getElementById("myselect").options[document.getElementById("myselect").selectedIndex].innerHTML;
if(myObject[key] != undefined)
{
//That means there is values for this key.
//Loop through values or do whatever you want with myObject[key].
for(var i = 0; i < myObject[key].length; i++)
{
window.alert("" + myObject[key][i]);
}
}

Related

populate dropdownlist from jsonresult using .each

I have a dropdown list that I need to dynamically populate based on the selection of another. It all works up to the point that I have to render the new data in the dropdown list after clearing the list first. The list clears, but then fails to populate the new data being returned from the controller. I am attempting to use .each for this.
Here's the controller method in question:
[AcceptVerbs(HttpVerbs.Get)]
public JsonResult UpdateDocumentSubType(string DocumentType)
{
List<SelectListItem> DocumentSubTypeList = new List<SelectListItem>();
PropertyModel model = new PropertyModel();
int DocTypeID = 0;
//get DocTypeID
DocTypeID = model.GetDocTypeID(DocumentType);
//gets new document subtype list
DocumentSubTypeList = model.GetDocumentSubTypes(DocTypeID);
//return document subtype list
return Json(DocumentSubTypeList, JsonRequestBehavior.AllowGet);
}
As you can see, I'm returning a serialized json result of List.
On the view, I have the following:
$.ajax({
url: '#Url.Action("UpdateDocumentSubType","Document")',
type: 'GET',
dataType: "json",
data: { DocumentType: SelectedDocTypeText },
async: true,
success: function (data) {
var select = $("#Docs_DocumentSubTypeID");
select.empty();
$.each(data, function (index, item) {
select.append($('<option></option>').val(item).html(index));
});
}
});
This is where it all falls apart. The code hits select.empty(): and executes it successfully, but then as the "text" value of the SelectListItem, it instead provides the index element of the array of objects. Essentially, the tags render something like this:
<option value="[object Object]">1</option>
<option value="[object Object]">2</option>
<option value="[object Object]">3</option>
<option value="[object Object]">4</option>
I have verified that the data IS being passed. When I take the .each and put it in its own function, call that function, and add "debugger;" to it, I can see the data in the resulting "data" as four elements of [object, object].
As you may have guessed, JQuery isn't my strong suit, so any assistance would be appreciated. :)
First you should not be returning List<SelectListItem> in your UpdateDocumentSubType method - there is no point returning the extra properties of SelectListItem back to the client when you never use them. All you need to return is an anonymous object containing 2 properties, one for the option value, and one for its display text.
You have not shown the model,but assuming it contains properties say int ID and string Name, then it would be (say)
var data = db.YourTable.Where(...).Select(x => new
{
Value = x.ID,
Text = x.Name
};
return Json(data, JsonRequestBehavior.AllowGet);
The reason why your seeing value="[object Object]" is that your returning an array of complex objects so item in $.each(data, function (index, item) { is referring to an object containing properties Value, Selected, Text, Group etc. (i.e. the properties of SelectListItem), so you script needs to be
$.each(data, function (index, item) {
select.append($('<option></option>').val(item.Value).html(item.Text));
});
I am new as well so this might not be correct.
Try
$('<option></option>').val(item[index]).html(index));
or
$('<option></option>').val(item[0]).html(index));
instead of what you wrote.
I need some more information. Can you share the github repo?
I am working on something very similar and this is what I did:
(Look at render function from line 85 to 96)
https://github.com/stephenhu3/codepal/blob/development/js/youtubeComponent.js
It worked for me.

Passing a variable inside a LINQ.js query

I am trying to query my JSON data which is stored in data.json file.
I successfully got desired result when i give static value inside the linq query but when i am passing a variable after user chooses a value from drop down menu, the linq query is not taking its dynamic value. here is my working code for static value.
$("#community").change(function() {
$.ajax({
url: 'json/data.json',
type: 'get',
dataType: 'json',
success: function(searchres) {
//console.log(searchres);
/////////////////////////////assigning searched results to handlebar.js
var community = $('#community').val();
var queryResult = Enumerable.From(searchres)
.Where("$.kls_commId = 7 ")
.ToArray();
console.log(queryResult);
//var bb = Handlebars.compile($('#beds').html());
// $('.mybeds').append(bb(responseBeds));
/////////////////////////////assigning searched results to handlebar.js
}
});
});
Now i have to pass the select box value inside the where clause,
i tried, Where("$.kls_commId = community ") or Where("$.kls_commId = $('#community').val() ") but its not working.
got the answer. i had to use .Where("$.kls_commId == " +community)
I am the author to jinqJs
Using jinqJs you could access outside variables by doing the following:
var nm = 'Tom';
result = jinqJs()
.from(data1)
.where ('Name == ' + nm)
.select(predicate);

Parsing JS array with JS and then passing it to PHP

I'm making a system for calculating road taxes in the netherlands, there for i got a few JS arrays (where the data is in) which i'm parsing with JS (all at the same time, because it's the same format of data), then passing it to PHP as JSON format using the XMLHttpRequest object.
For this i first made this data mapper:
var roadTaxData = {
provinceWeightFuelPricesData: {
personen_auto: {
noord_holland: dataNoordHolland,
zeeland: dataZeeland
//TODO: Add all the provinces with it's data to the personen_auto object
},
kampeer_auto: {
noord_holland: dataNoordHolland2,
zeeland: dataZeeland2
}
}
}
The format of this is:
Vehicle type
Which province
The data belonged to that province.
I've then made this small parser to parse it to an array:
/*
Loop through all the specific vehicle types inside the provinceWeightFuelPricesData object
*/
for (var vehicleType in roadTaxData.provinceWeightFuelPricesData) {
/*
Where the data is getting stored for each vehicle type
*/
var data = {},
/*
Every province with its data contained in the vehicle type
*/
provinces = roadTaxData.provinceWeightFuelPricesData[vehicleType];
/*
Loop through all province's with its data in the specific vehicle type
*/
for (var province in provinces) {
/*
Define each province data
*/
var provinceData = provinces[province];
/*
Add the province to the object as an key
*/
data[province] = [];
/*
Loop through the data which belongs to every province
*/
for (var provinceDataIndex = 0; provinceDataIndex < provinceData.length; provinceDataIndex++) {
/*
Add the province data to the array
*/
data[province].push(provinceData[provinceDataIndex]);
}
console.log('Parsed a the province: ' + province + " from the vehicle type " + vehicleType);
console.log('');
}
console.log('Parsed the vehicle type: ' + vehicleType);
console.log('');
console.log(data);
passToPHP(vehicleType, JSON.stringify(data));
}
This is all going great, and gives me back the correct array with data when i do this:
console.log(data);
But when i've passed it to PHP with this method:
function passToPHP (paramName, data) {
if (typeof paramName === "string" && typeof data === "string") {
var httpc = new XMLHttpRequest(); // simplified for clarity"
httpc.open("POST", INSTALL_FILE, true); // sending as POST
httpc.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
/*
For testing
*/
httpc.onreadystatechange = function () { //Call a function when the state changes.
if (httpc.readyState == 4 && httpc.status == 200) { // complete and no errors
console.log(httpc.responseText); // some processing here, or whatever you want to do with the response
}
};
httpc.send(paramName + "=" + data);
}
}
With this PHP file:
header('Content-Type: application/json');
$personen_auto = $_POST['personen_auto'];
$kampeer_auto = $_POST['kampeer_auto'];
print_r(json_decode($personen_auto));
print_r(json_decode($kampeer_auto));
I get this error first, which doesn't reconize the kampeer_auto index from $_POST, which i actually send:
Notice: Undefined index: kampeer_auto in
C:\Users\Bas\Documents..\Cars\install.php on line 6
Then the data log of the personen_auto object.
Then another error with this message, which does't reconize the personen_auto index, which i also just parsed and printed out?
Notice: Undefined index: personen_auto in
C:\Users\Bas\Documents..\Cars\install.php on line 5
Questions
How does this come that it doesn't reconize those $_POST variables?
How will i be able to make PHP receive more then only 1 $_POST index at the time?
My own try
I've tried putting the passPHP() method outside of the for loop, like this:
/*
Loop through all the specific vehicle types inside the provinceWeightFuelPricesData object
*/
for (var vehicleType in roadTaxData.provinceWeightFuelPricesData) {
/*
Where the data is getting stored for each vehicle type
*/
var data = {},
/*
Every province with its data contained in the vehicle type
*/
provinces = roadTaxData.provinceWeightFuelPricesData[vehicleType];
/*
Loop through all province's with its data in the specific vehicle type
*/
for (var province in provinces) {
/*
Define each province data
*/
var provinceData = provinces[province];
/*
Add the province to the object as an key
*/
data[province] = [];
/*
Loop through the data which belongs to every province
*/
for (var provinceDataIndex = 0; provinceDataIndex < provinceData.length; provinceDataIndex++) {
/*
Add the province data to the array
*/
data[province].push(provinceData[provinceDataIndex]);
}
console.log('Parsed the province: ' + province + " from the vehicle type " + vehicleType);
console.log('');
}
console.log('Parsed the vehicle type: ' + vehicleType);
console.log('');
//console.log(data);
}
passToPHP(vehicleType, JSON.stringify(data));
But that passed only one variable to PHP (which was kampeer_auto).
the code is sending only one vehicleType per call to php. The relevant code is
for (var vehicleType in roadTaxData.provinceWeightFuelPricesData) {
data = ...
passToPHP(vehicleType, JSON.stringify(data));
}
The first call passes 'personen_auto' only (and kampeer_auto is undefined); the second call passes only 'kampeer_auto' and personen_auto is undefined.
The revised version of the code that moves passToPHP outside the loop still resets data each time through the loop, so at the bottom data will contain only the very last auto's provinces.
To pass all autos, data needs to be appended to (not re-initialized), data has to be gathered into auto-specific sections (not intermingled), and passToPHP needs to build a multi-parameter query string, one per auto. All that will pretty much rebuild the roadTaxData object.
Or just pass all of roadTaxData.provinceWeightFuelPricesData to php and have php loop and separate the auto types.
Edit: you don't need to convert objects to arrays when passing them to php. Php's json_decode() can decode objects into associative arrays when the optional second parameter is set to true, as json_decode($data, true). Simply
passToPHP('json', JSON.stringify(roadTaxData.provinceWeightFuelPricesData));
and in php
$data = json_decode($_POST['json'], true);
$kampeer_auto = $data['kampeer_auto']);
$personen_auto = $data['personen_auto']);
try passing the data to php as an un-parsed json string, and parse it explicitly with json_decode.
So send a single $_POST parameter json=string (string is the urlencoded JSON.stringify of the data), and have php decode json_decode($_POST['json'], true). That should return an array that represents the js object.
Try putting declaration for data outside the loop. It's currently getting reset/cleared for each entry in roadTaxData.provinceWeightFuelPricesData so you will only ever send the last entry to the server.
var data = {};
for (var vehicleType in roadTaxData.provinceWeightFuelPricesData) {
Then, as #Andras suggested, you need to decode the JSON on the server side:
$data = json_decode( $_POST['json'], true );
$personen_auto = $data['personen_auto'];
$kampeer_auto = $data['kampeer_auto'];

json result display first value

I have found several posts similar to this topic but nothing I have tried has actually worked. My question is simple and should be easy to answer. My return json object will have one key and one value. For my code below, the alert shows "[{"DISCOUNT":1}]" and all I am trying to do is parse out the "1" and display it. Ultimately, I want to plug that value into a variable and use for multiplication, but I can't even get the darn number to display by itself. My code is below:
function codeMatchTest() {
if ($('#dbReturnString').val() == '') {
alert("Please enter a discount code.");
} else {
$.ajax({
type: "POST",
url: "PROMO.svc/MatchCode",
contentType: "application/json",
dataType: "json",
data: JSON.stringify({ codeInput: $('#dbReturnString').val().toLowerCase() }),
success: function (json) {
alert(json.d);
/*alert (json.d.discount); // getting "undefined"
$.each(json.d, function (key, value) {
var discount = value;
});
alert("Success: " + discount); //getting "undefined" */
},
error: function () {
alert("There was an error with your request.");
}
});
}
}
I have found no good references on how to actually use the data in a json object. My json object will only consist of a single key and value and I will only ever need to use the value.
Also, I have tried several iteration using $.each and none work. Based on the jquery documentation, it should be very easy but I am having not luck.
If your alert is showing "[{"DISCOUNT":1}]" that means you have an object within an array.
try alert(json.d[0].DISCOUNT);
JSON parsed objects are case sensivetive, plus its seems that json.d contains a string (wich seems to be in json) rather than an object. Try:
var discount = JSON.parse(json.d);
discount = discount[0].DISCOUNT;
success: function(json) {
alert(json.d[0]["DISCOUNT"]);
}
First comment on your code, you are reinventing what jQuery does.
data: JSON.stringify({ codeInput: $('#dbReturnString').val().toLowerCase() }),
It should just be
data: { codeInput: $('#dbReturnString').val().toLowerCase() },
Now to get the data it is simple, you are returning an array with an object in it.
Let us look at it as a regular variable and not an Ajaqx call.
var json = [{"DISCOUNT":1}];
So you got an array? How do you get the object inside of it? You reference the index. Since you said there will only be one index being returned, than use [0] to access it.
success: function (json) {
alert(json[0].DISCOUNT);
To access the first item from the json you may use
alert(json.d[0].DISCOUNT);
Because json.d is an array and it contains one object which is 0 index. So, json.d[0] will select the first item/object from the array and using .DISCOUNT you can access the object's property. It's also possible to access the property like
alert(json.d[0]["DISCOUNT"]);
Try this way
You can use JSON.parse(json.d) / json.d
var data = json.d;
for(i=0;i<data.length;i++) {
alert(data[i].fieldname);
}

Deleting items from an array causes Uncaught TypeError

I have a few jQuery plugins that I made - all parse JSON feeds and render them using Mustache.js; each plugin takes an integer value of how many items to display.
I received a Uncaught TypeError: Cannot read property 'link' of undefined when trying to parse the Stack Overflow JSON feed with the following code:
$.ajax({
type: 'GET',
url: query,
contentType: "jsonp",
dataType: 'jsonp',
success: function (jsonp) {
/* loop through JSON items converting the time from UNIX timestamp
** format to readable words by parsing it through timeConverter() */
var i;
for (i = 0; i < jsonp.items.length; i++) {
if (i > num-1){
delete jsonp.items[i];
} else {
jsonp.items[i].creation_date = timeConverter(jsonp.items[i].creation_date);
}
}
var output = Mustache.render(must_template, jsonp);
element.html(output);
return element;
} //EOF CALLBACK
}); //EOF AJAX
As a quickfix I disabled the truncation by simply commenting out the delete operation. The error suggests that Mustache.js is trying to access part of the JSON object which no longer exists; yet the delete operation clearly only affects items which are above the user-defined limit.
When this behaviour occured there were still 20 items in the array.
Note:
Yes, I've answered this question myself; however - I'm more than willing to accept another answer if it shows best practice, a neater way or improves upon my answer in some way. :)
delete is a "lower-level" operator compared to arrays. It directly removes the object property, bypassing all the specific array logic and hence does not update the length of the array.
If you want to delete an element from an array, use either .splice [MDN], or in your case you can simply set the length of the array and iterate over the remaining elements afterwards:
jsonp.items.length = Math.min(num, jsonp.items.length);
for (i = 0; i < jsonp.items.length; i++) {
jsonp.items[i].creation_date = timeConverter(jsonp.items[i].creation_date);
}
Delete is not changing array count as you already found out, it's only removing key. To remove items from array you can use splice. Example:
var array2 = [ 1, 2, 3, 4 ];
array2.splice(2, 1);
console.log('---------------------------');
console.log(array2.length); // 3
console.log(array2[0]); // 1
console.log(array2[1]); // 2
console.log(array2[2]); // 4
console.log(array2[3]); // undefined
Working sample: http://jsfiddle.net/qbXjp/1/
After much googling I couldn't find anything, even StackOverflow had failed me. Then, by chance, I came across this unintended side-effect of my 'quick hack' of commenting out the delete line..
Due to the fact I hadn't commented out the whole if/else block, my timeConverter() function wasn't being ran on the items which would ordinarily be deleted. This confirmed that the combination of for() and if(){} / else{} were working correctly. So it appeared as though Mustache.js was trying to access items that were already deleted! Almost as if the length property of the items[] array wasn't being updated when items were being deleted.
I made a jsFiddle test case and this confirmed it was the issue. Here's the code and ouput:
$.ajax({
type: 'GET',
url: query,
contentType: "jsonp",
dataType: 'jsonp',
success: function (jsonp) {
/* loop through JSON items converting the time from UNIX timestamp
** format to readable words by parsing it through timeConverter() */
var i;
for (i = 0; i < jsonp.items.length; i++) {
if (i > num-1){
console.log("Deleting item. Current Count: "+jsonp.items.length);
delete jsonp.items[i];
console.log("Deleting item. New Count: "+jsonp.items.length);
} else {
jsonp.items[i].creation_date = timeConverter(jsonp.items[i].creation_date);
}
}
console.log(jsonp);
return element;
} //EOF CALLBACK
}); //EOF AJAX
I tried a quick fix of using a counter to count each deletion, and then subtracting the deletion counter from the length property (jsFiddle):
$.ajax({
type: 'GET',
url: query,
contentType: "jsonp",
dataType: 'jsonp',
success: function (jsonp) {
/* loop through JSON items converting the time from UNIX timestamp
** format to readable words by parsing it through timeConverter() */
var i, deleted = 0;
for (i = 0; i < jsonp.items.length; i++) {
if (i > num-1){
delete jsonp.items[i];
deleted++;
} else {
jsonp.items[i].creation_date = timeConverter(jsonp.items[i].creation_date);
}
}
jsonp.items.length -= deleted;
console.log(jsonp);
return element;
} //EOF CALLBACK
}); //EOF AJAX
Here was the output this generated:
This code then ran fine when placed back in to the test environment and utilised with Mustache.js. Using the delete keyword doesn't affect the length property when used on an array
Coming from a Java background I'd taken for granted the fact that length is a property, and not a function - and therefore it isn't nessacerily updated upon any changes being made to the array. A stupid mistake that cost me more time than it should've! However, I couldn't find any other posts regarding this so I thought I'd post it up in the hope it can help anyone else in a similar position!

Categories