Reputation: 2013
i have a partial view "_SearchPanel" that has year list dropdown, a classes multiselect control, (some other drop downs - ommitted) and a search button.
I want that when i change selection in year list drop down, only my classes list is refreshed/updated, and not the whole partial view on page.
So i use a JsonResult action in my controller (as opposed to the first time load)
public JsonResult BindClasses(int yearId)
{
ClassRepository repClass = new ClassRepository("name=ge");
YearRepository repYear = new YearRepository("name=ge");
var dataClass = repClass.GetClassesByYear(yearId);
var groupedClassOptions = dataClass.GroupBy(x => x.grade).Select(x => new OptionGroupVM()
{
GroupName = "Grade " + x.Key.ToString(),
Options = x.Select(y => new OptionVM()
{
Value = y.classID.ToString(),
Text = y.classname
})
});
return Json(groupedClassOptions);
}
My javascript
var dropDownYear = $('#ddlYear');
dropDownYear.change(function(){
$("#classList").load(url, {yearId: $(this).val()}, function(result){
setOptions($('#classList'), @Html.Raw(Json.Encode(new List<int>(){})), result);
});
});
now the problem is this result is not considered as an object as was the first time (onpageload) here:
jQuery(function ($) {
setOptions($('#classList'), @Html.Raw(Json.Encode(Model.SelectedClasses)), @Html.Raw(Json.Encode(Model.ClassOptions)));
}
How do i correct/cast it to be considered as Model.ClassOptions(type: GroupOptionsVM List) object instead of a Json
What I have tried
var url = '@Url.Action("BindClasses", "Maps")';
var dropDownYear = $('#ddlYear');
dropDownYear.change(function(){
$("#classList").load(url, {yearId: $(this).val()}, function(result){
@{var x = new List<OptionGroupVM>();}
x = result;
setOptions($('#classList'), @Html.Raw(Json.Encode(new List<int>(){})), x);
});
});
this gives me some syntax errors!!
UPDATE
[Referring to the previous question Stephen linked in comments] Since i had to do it for two dropdown lists with slight difference i had created setOptions function in my script
function setOptions(listBox, selected, groups) {
// Generate options
createGroupedOptions(listBox, selected, groups);
// Attach plug-in
listBox.multiselect({ enableClickableOptGroups: true, onChange: function(){
var selectedClassItems = this.$select.val();
} });
}
function createGroupedOptions(element, selected, groups) {
for (var i = 0; i < groups.length; i++) {
var group = groups[i];
var groupElement = $('<optgroup></optgroup>').attr('label', group.GroupName);
for (var j = 0; j < group.Options.length; j++) {
var option = group.Options[j];
var optionElement = $('<option></option>').val(option.Value).text(option.Text);
if (selected) {
if (selected.toString().indexOf(option.Value) >= 0) {
optionElement.attr('selected', 'selected')
}
} else {
if (option.IsSelected) {
optionElement.attr('selected', 'selected')
}
}
$(groupElement).append(optionElement);
}
$(element).append(groupElement);
}
}
CALLING setOptions function
setOptions($('#classList'), @Html.Raw(Json.Encode(Model.SelectedClasses)), @Html.Raw(Json.Encode(Model.ClassOptions)));
setOptions($('#indicatorList'), @Html.Raw(Json.Encode(Model.SelectedIndicators)), @Html.Raw(Json.Encode(Model.IndicatorOptions)));
Upvotes: 1
Views: 474
Reputation:
Your returning json, so using .load()
makes no sense (you would typically use that when the method your calling returns a partial view).
Change your script to create the <optgroup>
and <option>
elements based on your data your method returns
var url = '@Url.Action("BindClasses", "Maps")';
var dropDownYear = $('#ddlYear');
dropDownYear.change(function() {
$.post(url, { yearId: $(this).val() }, function(data) {
$.each(data, function(index, item) {
var group = item.GroupName;
// use the above to build your <optgroup> element
$.each(item.Options, function(index, item) {
var value = item.Value;
var text = item.Text;
// use the above to build your <option> elements and append to the <optgroup> element
});
// append the <optgroup> to the <select id="classList"> element
});
});
});
Note the details of the code for generating the elements are in the answer to your previous question
Upvotes: 1
Reputation: 3703
You are trying to mix client side code (jQuery) with server side code (.NET) and it won't work. @Html.Raw and JsonEncode are server side methods. You can't use them after the page loads.
In essence, you need to either use jQuery for all of your page interaction and manage the state of the page on the client side or use full MVC (postback) and do everything on the server.
There are technically other options but I just wanted to address the fundamental issue with what you have tried so far.
Upvotes: 0