Can't Filling DropDownList with Ajax in MVC - c#

Everything seems OK but value shows empty..
I have 2 dropdownlist, when I choose first one, I got the index and used ajax to fill other dropdownlist.. But problem is that I dont have result.. loop that is in ajax, doesnt work.. and I checked web tool of firefox, result seems empty, but in C# code, the list has items..
so here is my ajax
$.ajax({
url: "#Url.Action("ElectionList", "Home")",
type: "GET",
dataType: "json",
data: { electionTypeId: selectedId },
success: function (data) {
if (data != null) {
//HERE IS WORKING
alert("OK");
electionCombo.html('');
$.each(data, function (index,item) {
//here is not working !!!
alert("hobaaa: " + index);
alert("data: " + item.Text);
// alert(option.ID + " " + option.politicName);
// electionCombo.append($('<option></option>').val(option.Value).html(option.Text));
});
}
here is my c# code
[AcceptVerbs(HttpVerbs.Get)]
public JsonResult ElectionList(int electionTypeId)
{
var service = new EvoteServicesProviderClient();
try
{
var electtionType = service.getAllElectionTypes().FirstOrDefault(e => e.ID == electionTypeId);
var res =
service.searchElectionByType(electtionType.electionTypeName)
.ToList()
.Where(e => e.startDate >= DateTime.Now)
.Select(e => new SelectListItem
{
Value = e.ID.ToString(),
Text = e.politicName
});
var list = new SelectList(res, "Value", "Text");
return Json(list, JsonRequestBehavior.AllowGet);
// return Json(new { success = true, result = list },
// JsonRequestBehavior.AllowGet);
}
catch{}
return Json(new { success = false, message = "An error occured" }, JsonRequestBehavior.AllowGet);
}
this is the html side
#using (Html.BeginForm("ElectionList", "Home", FormMethod.Post, new {#class = "form-horizontal", id = "electionlistform"}))
{
#Html.LabelFor(m => m.SelectedElectionId, new {#class = "col-md-2 control-label"})
#Html.DropDownListFor(m => m.SelectedElectionId, Model.ElectionList, new {#class = "form-control", id = "electionList"})
#Html.ValidationMessageFor(m => m.SelectedElectionId)
}
As I wrote, the list is not empty (in actionresult ElectionList)
What I am missing?

Try this :
$.each(data, function () {
//here is not working !!!
alert("hobaaa: " + this.Value);
alert("data: " + this.Text);
});
You can access the property directly because it's json.
UPDATE
Just return the list server side :
var res =
service.searchElectionByType(electtionType.electionTypeName)
.ToList()
.Where(e => e.startDate >= DateTime.Now)
.Select(e => new SelectListItem
{
Value = e.ID.ToString(),
Text = e.politicName
});
return Json(res, JsonRequestBehavior.AllowGet);

What I do when I need to fill a dropdown is the same as you, but I'm using a for loop instead of each (maybe it's the same but for me it's working). And by the way, in your ajax code sample you are not closing the ajax function. Hope in your real code it's okay.
$.ajax({
url: "#Url.Action("ElectionList", "Home")",
type: "GET",
dataType: "json",
data: { electionTypeId: selectedId },
success: function (data) {
if (data != null) {
//HERE IS WORKING
alert("OK");
electionCombo.html('');
for (i in data) {
var result = data[i];
// electionCombo.append($('<option></option>').val(result.Value).html(result.Text));
}
}
});
By the way, if it's still not working , you could try a ViewModel with the options you need
public class ViewModelExample
{
public Int32 ValueOption { get; set; }
public String TextOption { get; set; }
}
And use it in your list instead of selectlist. With viewmodels I don't have problems getting the values with json.

Related

dropdown menu populate another c# mvc json ajax

Below is my code, I am not sure what i am doing wrong?
Ajax json jquery code
function FillCity() {
var countryid = $("select[name$='.countryid']").val(); //<---- this is dynamic
$.ajax({
url: "Controller/FillMyCity",
type: "POST",
dataType: "json",
data: { country: countryid } ,
success: function (city) {
$("select[name$='.cityid']").html(""); // <--- this is dynamic
$.each(city, function (i, pp) {
$("select[name$='.cityid']").append(
$('<option></option>').val(pp.cityid).html(pp.name));
});
},
error: function (err) {
alert(err);
}
});
}
Controller method
public JsonResult FillMyCity(int country)
{
var cities = db.Cities.Where(x => x.countryid == country).ToList().Select(item => new City
{
cityid = item.cityid,
name = item.name
}).AsQueryable();
return Json(cities, JsonRequestBehavior.AllowGet);
}
View
#Html.DropDownList("Country[" + i + "].countryid", (SelectList)ViewData[countries], string.Empty, new { #class = "form-control countries", #id = "mycountry" + i + "", #onchange = "FillCity()" })
#Html.DropDownList("City[" + i + "].cityid", new SelectList(Enumerable.Empty<SelectListItem>(), "cityid", "name"), "Select city", new { #class = "form-control cities", #id = "mycity" + i + "" })
Output
EmployeeName Country City
Jenny ddl of countries ddl of cities
John ddl of countries ddl of cities
Problem 1: When I select country for Jenny, the cities ddl for both Jenny + John both get populated with Jenny's Country's cities, but it should only just applied for Jenny. When I select country for John the cities ddl list doesn't get populate So only Jenny's works, John doesn't
Problem 2: Since it is a dynamic json jquery appended html, I am unable to save the cities value, this is due to the fact that it is dynamic and doesn't appear in the view source.
Your use of $("select[name$='.countryid']").val(); will only ever select the value of the first element that has a name attribute ending with .countryid.
In addition, you use of DropDownList("Country[" + i + "].countryid", ...) is not the correct way to generate controls for a collection and its unlikely that will ever bind correctly to your model, however you have not shown the model so that cannot be fixed, so based on your current code, your view should be
<div class="container">
#Html.DropDownList("Country[" + i + "].countryid", (SelectList)ViewData[countries], string.Empty, new { #class = "form-control countries" })
#Html.DropDownList("City[" + i + "].cityid", Enumerable.Empty<SelectListItem>(), new { #class = "form-control cities" })
</div>
and the script
$('.countries').change(function() {
var country = $(this).val();
var cities = $(this).next('.cities'); // get the associated cities dropdownlist
cities.empty(); // clear existing options
$.ajax({
url: '#Url.Action("FillMyCity")', // do not hard code url's
type: "POST",
dataType: "json",
data: { country: country } ,
success: function (data) {
if (data) {
cities.append($('<option></option>').val('').text('Select city'));
$.each(data, function (index, item) {
cities.append($('<option</option>').val(item.cityid).html(item.name));
});
} else {
// oops
}
},
error: function (err) {
alert(err);
}
});
});
and finally, return a collection of anonymous objects containing only the data you need in the view to avoid sending extra data that will not be used
public JsonResult FillMyCity(int country)
{
// No need for .ToList()
var cities = db.Cities.Where(x => x.countryid == country).Select(item => new
{
cityid = item.cityid,
name = item.name
});
return Json(cities); // its a POST so no need for JsonRequestBehavior.AllowGet
}

Refresh MVC Dropdownlist

I'd like to refresh an MVC Dropdownlist from a JsonResult method.
Here's the public method that returns the result:
[HttpPost]
[ValidateAntiForgeryToken]
[CustomAuthorize]
public JsonResult GetHtmlApplicationSelectionList()
{
try
{
List<SelectListItem> applicationList = new List<SelectListItem>();
SelectListItem defaultApplicationValue = new SelectListItem();
defaultApplicationValue.Value = "0";
defaultApplicationValue.Text = "-- Select Application --";
defaultApplicationValue.Selected = true;
applicationList.Add(defaultApplicationValue);
foreach (var app in businessLogic.GetApplications().Select(x => new SelectListItem { Value = x.ID.ToString(), Text = x.Name }))
{
applicationList.Add(app);
}
return Json(new { result = "success", list = applicationList }, JsonRequestBehavior.AllowGet);
}
catch(Exception ex)
{
return Json(new { result = "failure", message=ex.Message}, JsonRequestBehavior.AllowGet);
}
}
And here's the jQuery function that calls the POST method to get the updated list of applications:
function UpdateApplicationList() {
$.ajax({
url: 'Global/GetHtmlApplicationSelectionList',
type: 'POST',
dataType: 'json',
success: function (data) {
$('.applicationSelector').html('');
$('.applicationSelector').html(data);
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.responseText);
}
});
}
How can I force the $(.applicationSelector') dropdownlist to contain the new list without having to loop through the list retured as JSON? Is it possible to return the html of the list( applicationList) and just refresh the html using
$('.applicationSelector').html(data); ?
You need to append an <option> for each item.
This is the answer taken from this post which provides a pretty simple and straight forward example.
$.each(selectValues, function(key, value) {
$('#mySelect')
.append($('<option>', { value : key })
.text(value));
});
Where var selectValues is your JSON list

It is possible to refresh ViewBag value in the view?

I'm trying to do a dynamic dropdownlist :
I get the options of the dropdownlist from a database and put them in an objects list. In accordance with a checkbox value i remove objects from the list and set this list as a ViewBag value.
public ActionResult ThematicManagement(string Id, string IsAdult, string flagAdult)
{
.....
ViewBag.DDL = null;
var response = VodCatalogBUS.GetParentThematics();
List<oboThematic> list = new List<oboThematic>();
list = response.Data;
if (IsAdult == null || IsAdult == "false")
list.RemoveAll(x => x.IsAdult == true && x.Id != 1007);
else
list.RemoveAll(x => x.IsAdult == false && x.Id != 1007);
ViewBag.DDL = new SelectList(list, "Id", "Name");
....
Then in my view i fill the dropdownlist like that :
#Html.DropDownList("ParentThematic", (SelectList)ViewBag.DDL, new { #class="dropdown" })
<label><input type="checkbox" value="" id="ChkIsAdult" name="ChkIsAdult">Adulte</label>
There is no problems here, i obtain the dropdown list with 4 options after the RemoveAll in the controller. Then if i click the checkbox, i must obtain 3 other options.
So I use an ajax call to return into the controller in the aim to update Viewbag's value :
$('#ChkIsAdult').change(function () {
var IsAdult = $('#ChkIsAdult').is(':checked');
var url = dev + "/Legacy/ThematicManagement";
$.ajax({
url: url,
cache: false,
type: 'POST',
data: {
IsAdult: IsAdult,
flagAdult : 'true',
},
success: function () {
alert('test');
}
});
})
It works i return into the controller, but i think that the view isn't refresh so i retreive the old values (the 4 options) of the dropdownlist after clicking the checkbox.
I also try with ViewData and TempData to replace ViewBag but i've always the same proprem !
According to you, it is the good solution ? Can it works ?
Here is the response :
Controller
var response = VodCatalogBUS.GetParentThematics();
List<oboThematic> list = new List<oboThematic>();
list = response.Data;
list.RemoveAll(x => x.IsAdult == true && x.Id != 1007);
var responseAdult = VodCatalogBUS.GetParentThematics();
List<oboThematic> listAdult = new List<oboThematic>();
listAdult = responseAdult.Data;
listAdult.RemoveAll(y => y.IsAdult == false && y.Id != 1007);
ViewBag.DDL = new SelectList(list, "Id", "Name");
ViewBag.DDLAdult = new SelectList(listAdult, "Id", "Name");
View :
#Html.DropDownList("ParentThematic", (SelectList)ViewBag.DDL, new { #class="dropdown" })
#Html.DropDownList("ParentThematicAdult", (SelectList)ViewBag.DDLAdult, new { #class="dropdown" , #style="display:none"})
JS :
$('#ChkIsAdult').change(function () {
if ($('#ChkIsAdult').is(':checked')) {
$('#ParentThematic').hide();
$('#ParentThematicAdult').show();
var value = $('#ParentThematicAdult').val();
var IsAdult = $('#ChkIsAdult').is(':checked');
var url = dev + "/Legacy/ThematicManagement";
$.ajax({
url: url,
cache: false,
type: 'POST',
data: {
Id: value,
IsAdult: IsAdult
},
success: function (data) {
$('#result').empty().append($(data).find('table'))
}
});
}
else
{
$('#ParentThematic').show();
$('#ParentThematicAdult').hide();
var value = $('#ParentThematic').val();
var IsAdult = $('#ChkIsAdult').is(':checked');
var url = dev + "/Legacy/ThematicManagement";
$.ajax({
url: url,
cache: false,
type: 'POST',
data: {
Id: value,
IsAdult: IsAdult
},
success: function (data) {
$('#result').empty().append($(data).find('table'))
}
});
}
})

Passing response from ajax call to view in C#

I am using ajax to call an action in the controller. The code is like this
$('#kitchen').change(function () {
var selectedKitchen = $('#kitchen').val();
if (selectedKitchen != '') {
console.log("selected item:" + $('#kitchen').val());
$.ajax({
type: "GET",
url: "/Home/GiveInsitutionsWithoutResponsibility",
data: "id=" + selectedKitchen,
dataType:'json',
success: function (result) {
result = JSON.parse(result);
console.log(result.length);
},
error: function (error) {
console.log("There was an error posting the data to the server: ");
console.log(error.responseText);
}
});
}
});
Now what I want is to use the result coming from the server to populate a drop down on the client side. How should I do it? Is there a way for it or my approach here is wrong?
My result object is like this
{
Id: "04409314-ea61-4367-8eee-2b5faf87e592"
Name: "Test Institution Two"
NextPatientId: 1
OwnerId: "1"
PartitionKey: "1"
RowKey: "04409314-ea61-4367-8eee-2b5faf87e592"
Timestamp: "/Date(1417180677580)/"
}
The controller function is like this
public ActionResult GiveInsitutionsWithoutResponsibility()
{
var kitchenId = Request["id"].ToString();
Kitchen k = Kitchen.Get(kitchenId);
IEnumerable <Institution> ins = k.GetInstitutions();
IEnumerable<Institution> allIns = Institution.GetAll();
List<Institution> result = new List<Institution>();
bool contain = true;
int index = 0;
if (ins.Count() > 0)
{
for (int i = 0; i < allIns.Count(); i++, contain = true)
{
for (int j = 0; j < ins.Count(); j++)
{
if (allIns.ElementAt(i).Id == ins.ElementAt(j).Id)
{
contain = true;
break;
}
else
{
index = j;
contain = false;
}
}
if (!contain)
{
result.Add(allIns.ElementAt(index));
}
}
}
else
{
for (int i = 0; i < allIns.Count(); i++)
{
result.Add(allIns.ElementAt(index));
}
}
string response = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(result);
return Json(response, JsonRequestBehavior.AllowGet);
}
First your action method can be simplified to
public ActionResult GiveInsitutionsWithoutResponsibility(int ID)
{
Kitchen k = Kitchen.Get(ID);
var data = Institution.GetAll().Except(k.GetInstitutions(), new InstitutionComparer()).Select(i => new
{
ID = i.ID,
Name = r.Name
});
return Json(data, JsonRequestBehavior.AllowGet);
}
Note the Kitchen.ID is passed in the method parameter. The Linq query is used to select all Institution's then exclude any Institution's that already exist in the Kitchen, then creates a collections of anonymous object so unnecessary data is not sent to the client. The Json() method returns the data in the correct JSON format (calling JavaScriptSerializer().Serialize() is not required).
In order for .Except() to work with complex objects, you need a comparer
public class InstitutionComparer : IEqualityComparer<Institution>
{
public bool Equals(Institution x, Institution y)
{
if (Object.ReferenceEquals(x, y))
{
return true;
}
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
{
return false;
}
return x.ID == y.ID;
}
public int GetHashCode(Institution institution)
{
if (Object.ReferenceEquals(institution, null))
{
return 0;
}
return institution.ID.GetHashCode();
}
}
Next change the ajax method to
$('#kitchen').change(function () {
var selectedKitchen = $('#kitchen').val();
if (!selectedKitchen) {
return;
}
$.ajax({
type: "GET",
url: '#Url.Action("GiveInsitutionsWithoutResponsibility", "Home")', // don't hard code urls
data: { id: selectedKitchen }, // pass selectedKitchen to the id parameter
dataType:'json',
success: function (result) {
var select = $('YourDropDownSelector').empty().append($('<option></option>').val('').text('--Please select--'));
$.each(result, function(index, item) {
select.append($('<option></option>').val(item.ID).text(item.Name));
});
},
error: function (error) {
}
});
});
or you could use the short cut
$.getJSON('#Url.Action("GiveInsitutionsWithoutResponsibility", "Home")', { id: selectedKitchen }, function(result) {
$.each(result, .... // as above
});
Depending on the object from your controller, you could loop through your results data and .append this to your drop down list.
success: function (result) {
$.each(result, function(index, manager) {
$('select#yourId').append(
'<option value="' + result.Id + '">'
+ result.Name +
'</option>');
});
}
Your approach is fine, you will have to format the result to be added to combo box. For example, support on a page I have country and states combo box. Based on selected country, I need to populate state, so I will write following code:
$("#billingContactCountry").change(function (e) {
e.preventDefault();
var countryId = $("#billingContactCountry").val();
getStatesByCountry(countryId, "", "#billingContactState", "#billingContactZip");
});
function getStatesByCountry(countryId, stateId, stateCombobox, zipTextBox) {
$.ajax({
url: "#Url.Action("GetStatesByCountry", "Admin")",
data: { countryId: countryId },
dataType: "json",
type: "GET",
error: function (xhr, status) {
//debugger;
var items = "<option value=\"\">-Select State-</option>";
$(stateCombobox).html(items);
var zipMessage = validateZip(countryId, $(zipTextBox).val());
if (zipMessage != "The ZIP Code field is required.") {
$(zipTextBox).parent().find("span.field-validation-error").text(zipMessage);
}
$("div.overlay").hide();
},
success: function (data) {
//debugger;
var items = "<option value=\"\">-Select State-</option>";
$.each(data, function (i, item) {
items += "<option value=\"" + item.Id + "\">" + item.Name + "</option>";
});
$(stateCombobox).html(items);
if (stateId != "") {
$('#billingContactState').val(stateId);
}
var zipMessage = validateZip(countryId, $(zipTextBox).val());
if (zipMessage != "The ZIP Code field is required.") {
$(zipTextBox).parent().find("span.field-validation-error").text(zipMessage);
}
$("div.overlay").hide();
}
});
}
So basically interesting code is,
var items = "<option value=\"\">-Select State-</option>";
$.each(data, function (i, item) {
items += "<option value=\"" + item.Id + "\">" + item.Name + "</option>";
});
$(stateCombobox).html(items);
We are operating on each element returned from server to create option item for combo box.
As an aside, you should use #Url.Action as shown in example above.

Selected values in cascading dropdownlists reset on post

I have MVC4 web-application with 2 cascading dropdownlists (parent and child) and button with post action for filtering data dislpayed in grid depending on selected values in dropdownlists. Cascading dropdownlists I realized with Microsoft AJAX (Ajax.BeginForm helper), almost as described here: http://weblogs.asp.net/raduenuca/archive/2011/03/20/asp-net-mvc-cascading-dropdown-lists-tutorial-part-3-cascading-using-microsoft-ajax-ajax-beginform-helper.aspx. BTW, dropdownlists are located in partial view.
The problem is that when I click button, postback is performed and selected values in cascading dropdownlists are reset to original values, i.e. "Please, select value".
Does anybody know how to solve this problem?
Thanks in advance for all who give an answers!
Here is my code with partial view with cascading dropdownlists:
<script type="text/javascript">
$(function () {
$('#Sections').change(function () {
var sectionId = $("#Sections :selected").val();
if (sectionId != "") {
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
url: '#Url.Action("GetDocumentTypesList", "DocumentTypes")',
data: { "id": sectionId },
dataType: "json",
success: function (data) {
var items = "";
$.each(data, function (i, documentType) {
items += "<option value='" + documentType.Value + "'>" + documentType.Text + "</option>";
});
$('#Types').html(items);
},
error: function (result) {
alert('Service call failed: ' + result.status + ' Type :' + result.statusText);
}
});
}
else {
var items = '<option value="">Select</option>';
$('#Types').html(items);
}
});
});
#Html.DropDownList("Sections", new SelectList(ViewBag.Sections, "Id", "Name"), "Please select parent type", new { id = "Sections" })
#Html.DropDownList("Types", new SelectList(ViewBag.Types, "Id", "Name"), "Please select child type", new { id = "Types" })
And here is controller code for partial view:
public class DocumentTypesController : Controller
{
static List<DocumentType> documentTypes = DocumentsDAL.GetDocumentTypes(true, true, false);
// GET: /DocumentTypes/
public ActionResult Index()
{
var root = documentTypes.Where(d => d.ParentId == null).ToList();
ViewBag.Sections = root;
ViewBag.Types = new List<DocumentType> { new DocumentType { Id = -1, Name = "Select" } };
return PartialView("~/Views/Shared/_DocumentTypes.cshtml", root);
}
// Get values for parent dropdownlist.
[AcceptVerbs(HttpVerbs.Get)]
public JsonResult GetDocumentTypesList(string id)
{
var items = GetDocumentTypes(Convert.ToInt32(id)).Select(a => new SelectListItem
{
Text = a.Name,
Value = a.Id.ToString(CultureInfo.InvariantCulture)
});
return Json(items, JsonRequestBehavior.AllowGet);
}
// Get values for child dropdownlist.
[AcceptVerbs(HttpVerbs.Get)]
public JsonResult GetDocumentTypeData(string sectionId, string typeId)
{
var documentTypeData = GetDocumentTypes(Convert.ToInt32(sectionId))
.First(d => d.Id == Convert.ToInt32(typeId));
return Json(documentTypeData, JsonRequestBehavior.AllowGet);
}
private static IEnumerable<DocumentType> GetDocumentTypes(int id)
{
return documentTypes.First(d => d.Id == id).DocumentTypes;
}
}
And this is a base view where it's used partial one:
#using (Ajax.BeginForm("Index", null, new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "documentsGrid"
}, new { #class = "form-inline" }))
{
<div>
#{ Html.RenderAction("Index", "DocumentTypes", new { area = "" }); }
</div>
<p class="form-inline">
#Html.LabelForModel(#Resources.LabelPeriodFrom)
#Html.Raw(" ")
#Html.TextBox("periodFrom", "", new { #class = "input-small" })
#Html.Raw(" ")
#Html.LabelForModel(#Resources.LabelPeriodTo)
#Html.Raw(" ")
#Html.TextBox("periodTo", "", new { #class = "input-small" })
#Html.Raw(" ")
<input type="submit" class="btn" value="Filter" />
</p>
}
And controller for basic view with post-action Index, which fired when user press button:
public class IssuerDocumentsController : Controller
{
static readonly IEnumerable<IssuerDocument> Documents = DocumentsDAL.GetDocuments(1, 1).AsEnumerable();
[HttpPost]
public ActionResult Index(FormCollection collection)
{
var documents = Documents.AsEnumerable();
// Check if document section filter is applied.
if (!string.IsNullOrEmpty(collection.Get("Sections")))
{
var documentSectionId = Convert.ToInt32(collection.Get("Sections"));
documents = documents.Where(d => d.SectionId == documentSectionId);
}
// Check if document type filter is applied.
if (!string.IsNullOrEmpty(collection.Get("Types")))
{
var documentTypeId = Convert.ToInt32(collection.Get("Types"));
documents = documents.Where(d => d.TypeId == documentTypeId);
}
return View(documents);
}
}

Categories

Resources