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.
Related
I have the following controller action:
public JsonResult GetInvestors(int bank)
{
var investors = _context.Investors
.Where(i => i.BankNumber == bank)
.Select(i => new { InvestorId = i.InvestorId.ToString(), InvestorName = i.InvestorName + " (" + i.BankNumber + ")" })
.OrderBy(i => i.InvestorName)
.ToDictionary(i => i.InvestorId, i => i.InvestorName);
return Json(investors, JsonRequestBehavior.AllowGet);
}
And the following javascript to call that action that for now just starts the debugger so I can browse the result:
function getInvestors(bank)
{
$.ajax
({
url: "/InvestorDetail/GetInvestors",
type: "POST",
data: { bank: bank },
dataType: "json",
success: function (returnedData) { debugger; }
});
}
If I watch investors in the controller action, it is sorted by the investor name, which is what I want. However, when I get to the javascript debugger and watch returnedData, the data comes in sorted by the investor ID.
Alternately, if I put OrderBy after ToDictionary and order by Value, in the javascript debugger the json structure of the result is different but it is sorted by investor name like I want.
Why would the sort order change when returned from a Dictionary?
Thank you.
For purposes of enumeration, each item in the dictionary is treated as a KeyValuePair structure representing a value and its key. The order in which the items are returned is undefined.
See official msdn documentation
You can use sorted Dictionaries though, or sort it properly on the client side.
You can't sort a dictionary, although you can get a representation of a sorted dictionary!
You could try something like
import collections
Dictionary_Sorted = collections.OrderedDict(x)
x being an object with key valued pairs.
This is the same case for C# as well.
I like to change my Dictionary to a list by say.
var newList = thisDictionary.ToList();
newList.Sort((a,b) => a.Value.CompareTo(b.Value));
I like the one liner approach. It is simple and elegant.
If you would like to sort it descending then switch the values as such.
newList.Sort((a,b) => b.Value.CompareTo(a.Value));
Im trying to populate a select (with the values from an array) depending on the option they select from the first dropdown
I have the arrays in my function, like so:
residential = ["R1_:_Single_Private_Dwelling","CH1_:_Self-Catering_Holiday_Unit","R2_:_Flats_or_Maisonettes_Up_to_3_floors_Purpose_Built","R3_:_Flats_or_Maisonettes_4_floors_and_over_Purpose_Built","CC7_:_Time_Share_Complex","R4_:_Houses_Converted_to_Flats_Up_to_2_Floors","R5_:_Houses_Converted_to_Flats_3_floors_and_over","MR_:_Hostel","R6_:_HMO","CC_:_Camping_Site","CC1_:_Caravan_Park","CC5_:_Chalet_Park","CC6_:_Caravan_And_Chalet_Park_","CC_:_Gypsy_Caravan_Site","XX1_:_Other"]; institutionalVal = ["MH2_:_Hospital","MH3_:_Hospital_(private)","MR1_:_(Care)_Home_for_older_people_(Over_65)","MR2_:_(Care)_home_for_adult_placements_"];
The user is selecting from a dropdown, with an ID of 'residential' for example and I want to populate a second select with the values from the array above.
So I'm grabbing the ID of the selected option, like so:
var org_cat = $(this).children(":selected").attr("id");
So, the value of org_cat for example would be 'residential', so I'm thinking i can just try and iterate through this as the array is called 'residential'
So I'm trying to loop through the array as below:
$.each(org_cat, function(value) {
$('#area_usage')
.append($("<option></option>")
.attr("value", value)
.text(value));
});
BUT, the variable 'org_cat' is not being seen as the array.
What am i doing wrong, do I have to tell JQuery that its an array somehow?
This is the error I'm getting.
TypeError: invalid 'in' operand a
What you are trying to do is referencing the variable "residential" (that is an array) by using a string. So for that you can have an object like:
var org_cat = $(this).children(":selected").attr("id"); // = "residential"
var obj =
{
"residential": ["R1_:_Single_Private_Dwelling","CH1_:_Self-Catering_Holiday_Unit","R2_:_Flats_or_Maisonettes_Up_to_3_floors_Purpose_Built","R3_:_Flats_or_Maisonettes_4_floors_and_over_Purpose_Built","CC7_:_Time_Share_Complex","R4_:_Houses_Converted_to_Flats_Up_to_2_Floors","R5_:_Houses_Converted_to_Flats_3_floors_and_over","MR_:_Hostel","R6_:_HMO","CC_:_Camping_Site","CC1_:_Caravan_Park","CC5_:_Chalet_Park","CC6_:_Caravan_And_Chalet_Park_","CC_:_Gypsy_Caravan_Site","XX1_:_Other"]; institutionalVal = ["MH2_:_Hospital","MH3_:_Hospital_(private)","MR1_:_(Care)_Home_for_older_people_(Over_65)","MR2_:_(Care)_home_for_adult_placements_"];
}
And get the array "residential" thought referencing the index in the object like:
obj[org_cat]
So on the jQuery each:
$.each(obj[org_cat], function(value) {
$('#area_usage')
.append($("<option></option>")
.attr("value", value)
.text(value));
});
Or if your variable "residential" is global, you can refer it through window object like window[org_cat] instead of obj[org_cat]
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]);
}
}
I have a script that sends the values to the controller. Everything works fine when the value of the digit. At values larger displays only the last digit. String assigned to rigidly as bad. Debugger displayed on the controller is that the value passed is correct.
script
...
$.each(data, function (i, kkk) {
document.getElementById("sum").value = kkk
});
controller
public ActionResult Fun(int some, int some1)
{
string xxx = "18";
if (HttpContext.Request.IsAjaxRequest())
return Json(xxx
, JsonRequestBehavior.AllowGet);
return RedirectToAction("Index");
}
view
<input type="text" name="sum" id="sum"/>
displays 8...should be 18.
Why is this happening? Why the return value is truncated?
It looks like the result is treated as a char array. When you iterate over data, it sets the last char as the value of the input. Get rid of the loop and it should be fine.
document.getElementById("sum").value = data;
Have a look at jQuery each function
It is setting the last character in the string to the value.
What you want to do is just set the value equal to the data returned without the loop.
I would use this:
$.ajax({
// edit to add steve's suggestion.
url: "/ControllerName/ActionName",
success: function(data) {
document.getElementById("sum").value = data;
}
});
I have a JSON which lists the values from database. Below is the JSON data of 2 rows from the database.
[{"Name":"P1","Description":"pd1","Value":"v1","Attribute":"a1"},{"Name":"P1","Description":"pd1","Value":"v2","Attribute":"a2"}]
database values are the result of a left join query. Only 'Value' and 'Attribute' fields are different. Can I append that fields to JSON instead of multiple sets of record? I know there is 'push' to do this, but I am unaware where and how to use this in my code. below is the code for fetching values from db and serializing the values.
GetProfileDataService GetProfileDataService = new BokingEngine.MasterDataService.GetProfileDataService();
IEnumerable<ProfileData> ProfileDetails = GetProfileDataService.GetList(new ProfileSearchCriteria { Name = strProfileName });
JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
string strSerProfileDetails = javaScriptSerializer.Serialize(ProfileDetails);
context.Response.ContentType = "text/json";
context.Response.Write(strSerProfileDetails);
Below is my getJSON
$(document).ready(function () {
$.getJSON('ProfileHandler.ashx', { 'ProfileName': 'Profile 1' }, function (data) {
$.each(data, function (k, v) {
alert(v.Attribute+' : '+v.Value);
});
});
});
Please help me here.
There are several things you can do.
Store value and attribute as arrays:
[{"Name":"P1","Description":"pd1","Value":["v1", "v2"],"Attribute":["a1", "a2"]}]
Or store them as a 'symbol'-separated string:
[{"Name":"P1","Description":"pd1","Value":"v1;v2"],"Attribute":"a1;a2"]}]
In order to use the first case, you'll have to try and figure out how to format the ProfileDetails in order to have javaScriptSerializer.Serialize parse it correctly. You will likely have to convert your data first in order for this to work (i.e. convert value and attribute to arrays).
For the second case to work you could modify your GetProfileDataService.GetList method so that values and attributes are merged to symbol-separated strings (something like this: GROUP BY to combine/concat a column)