Cascading dropdown lists in Mvc 4.0 - javascript

I have been trying to cascade dropdown lists. For this purpose I am using javascript in .cshtml page . Don't know what is the reason , I'm not able to even call Js method , leave alone the controller method which later needs to be called from within the Js method. Dropdowns are fetching the state and city data but I'm not getting the city according to the state selected.
<div class="editor-label">
#Html.LabelFor(model => model.State_Id)
</div>
<div class="editor-field">
#Html.DropDownList("State",null,"Select State", new {#class="span4", id="State"})
#Html.ValidationMessageFor(model => model.State_Id)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.CityId)
</div>
<div class="editor-field">
#Html.DropDownList("City",null,"Select City", new {#class="span4", id="City"})
#Html.ValidationMessageFor(model => model.CityId)
</div>
<script src="~/Scripts/jquery-1.7.1.js"></script>
<script src="~/Scripts/jquery-1.7.1.min.js"></script>
<script type="text/javascript" >
$(document).ready(function(e) {
$("#State").change(function (e) {
var selectedValue = $(this).val();
if(selectedValue != "Select") {
$.ajax({
url: '#Url.Action("GetCities","Employer")',
type: 'Post',
//data: { "selectedValue": selectedValue},
data: {id: $("#State").val()},
dataType: 'json',
success: function(response) {
var items = "";
$.each(response, function(i, city) {
$("#City").append('<option value="' + city.Value + '">' + city.Text + '</option>');
});
},
error: function (ex) {
alert("Failed To Receive States" + ex);
}
});
}
});
});
</script>

#Html.DropDownListFor(x => x.LeagueId, Model.LeagueSL, "--Select League--", new { id = "ddlLeague"})
#Html.DropDownListFor(x => x.LeagueId, Model.DivisionSL, "--Select Division--", new { id = "ddlDivision"})
The Second DropDownList is empty, all it has is the option Label --Select Division--
On change event of the 1st dropdown make an AjaxRequest that fills the Second One.
var value = $("#DropDown1").val();
var ddlDivision = $("#DropDownDivision");
ddlDivision.html('');//clear current contents;
$.ajax({
url: "/Home/GetDivisions",
type: "GET",
data: { leagueId: value },
success: function (data) {
$.each(data, function (index, item) {
//item = this
//populate ddl
ddlDivision.append($('<option></option>')
.val(item.PropTwo)
.html(item.PropOne));
});
});
public JsonResult GetDivisions(int leagueId)
{
using (BaseballEntities context = new BaseballEntities())
{
var divisions = (from x in context.Table
where x.LeagueID == leagueId
select new
{
PropOne = x.DivisionName,
PropTwo = x.DivisionId
}).ToList();
return Json(divisions, JsonRequestBehavior.AllowGet);
}
}
Edit: As a Side Note it is better to use your Model to fill your dropdownList.
Give your model a SelectList property
public List<SelectListItem> LeagueSL { get; set; }//you will need to initialize in constructor
public ActionResult Index()
{
MyViewModel model = new MyViewModel();
using (MyEntities context = new MyEntities())
{
var leagueList = context.League.ToList();
foreach (var item in leagueList)
{
model.LeagueSL.Add(new SelectListItem() { Text = item.LeagueName, Value = item.LeagueId.ToString() });
}
}
return View(model);
}

Drop down lists are their own beast. You probably need to create the new OPTIONs using standard DOM methods inside the loop rather than jQuery's append method:
success: function(response) {
var items = "", option, $city = $("#City");
$.each(response, function(i, city) {
option = document.createElement("option");
option.value = city.Value;
option.innerHTML = city.Text;
$city.append(option);
});
},

Related

Loading dropdown list after modal for m is updated

I very new to MVC and I have an issue that was real easy in webforms. I have a drop down list on a form. I have a button that loads a modal form that allows the user to add an item to the DB on the fly. I then need to update the dropdown list with the new contents of the table. I realize I need ajax to do this but I am very confused on how to initiate the update!
I have the form with the following dropdown.
<div class="form-group form-group-sm required">
#Html.LabelFor(m => m.ListingData.Transmission, new { #class = "col-md-4 control-label" })
<div class="col-md-8">
#Html.DropDownListFor(m => m.ListingData.Transmission, (SelectList)ViewBag.TransmissionList, new { #class = "form-control"} )
#Html.ValidationMessageFor(m => m.ListingData.Transmission, "", new { #class = "text-danger" })
<p class="form-text"><a data-modal='' href='#Url.Action("QATransmission", "Admin", new { ListingId = Model.ListingData.ListingId}))' id=''>Quick Add Manufacturer</a></p>
</div>
</div>
I use this ajax in the main page to call the load the list code in the controller.
$(function () {
$.ajax({
type: "GET",
url: "Admin/LoadTransmissionList",
data: JSON,
cache: false,
success: function (data) {
$.each(data, function (index, value) {
$('#Transmission').append('<option value="' + value.TransmissionText + '">' + value.TransmissionText + '</option>');
});
}
});
});
This is my controller code for the list:
[HttpPost]
public JsonResult LoadTransmissionList()
{
var lstTrans = db.Transmissions.ToList();
List<SelectListItem> list = new List<SelectListItem>();
foreach (Transmission p in lstTrans)
{
list.Add(new SelectListItem() { Value = p.TransmissionText.ToString(), Text = p.TransmissionText.ToString() });
}
return Json(list, JsonRequestBehavior.AllowGet);
}
I have a modal form and it has a text box for entering a new list item. I need to save to the DB, which works but then! I cant come up with the reload the listbox contents part. Any help!
Thanks!
1)Make your code changes like this
success: function (data) {
$('#ListingData_Transmission').html("")
$.each(data, function (index, value) {
$('#ListingData_Transmission').append('<option value="' + value.TransmissionText + '">' + value.TransmissionText + '</option>');
});
}
hope this should work now
2) Make your form as a partial view and reload it whenever your saving something to DB.
Let me know if any issues

MVC 5 - Registering JavaScript events from partial view which uses BeginCollectionItem

I have a partial view which looks like this:
#model Whatever.Models.Jobs
#using (Html.BeginCollectionItem("JobRecords"))
{
<tr id="jobRow">
#Html.HiddenFor(m => m.Id)
<th width="40%">
#Html.EditorFor(m => m.Project, new { htmlAttributes = new { #class = "form-control", id = "project", list = "projectResults" } })
<datalist id="projectResults"></datalist>
#Html.ValidationMessageFor(m => m.Project, "", new { #class = "text-danger" })
</th>
</tr>
}
This is embedded in the parent view like:
#if (Model.JobRecords != null)
{
foreach (var item in Model.JobRecords)
{
Html.RenderPartial("_JobEditorRow", item);
}
}
It all works, but as you can see from the partial view I want to add a searchable box using data-list, so I add a method in my controller:
[HttpGet]
public JsonResult GetProjects(string query)
{
var list = unitOfWork.ProjectRepository.Get(c => c.Name.contains(query));
var serialized = list.Select(p => new { p.ProjectCode, p.Name});
return Json(serialized, JsonRequestBehavior.AllowGet);
}
And then add some javascript which uses AJAX to populate this data-list:
$(document).ready(function () {
var delay = 1000;
var globalTimeout = null;
function contractsCall() {
console.log("called");
$("#projectResults").empty();
$.ajax({
cache: false,
type: "GET",
contentType: "application/json;charset=utf-8",
url: "/MyController/GetProjects?query=" + $("#project").val()
})
.done(function (data) {
if (data[0] !== undefined) {
for (var i = 0; i < data.length; i++) {
$("#projectResults").append(
"<option value=" + data[i]["ProjectCode"] + ">" + data[i]["Name"] + " - " + data[i]["ProjectCode"] + "</option>"
);
}
} else {
$("#projectResults").empty();
}
});
}
$("#project").keyup(function (event) {
console.log("keyup");
if (globalTimeout !== null) {
clearTimeout(globalTimeout);
}
globalTimeout = setTimeout(function () {
globalTimeout = null;
contractsCall();
}, delay);
});
});
This javascript is included in the parent view which is also embedding the partial view. But I add a job record and type something in the input box, it doesn't do anything despite it having the id of project.
My question is, how can I register events that occur in partial views from a parent view; or if I could embed by javascript file in the partialview to fix this? And the more difficult question is, how can I prevent the duplication of ids when adding a job with BeginCollectionItem? Because adding multiple rows would add multiple project id input boxes.
Update
#Stephen helped me greatly to fix this issue, I removed the <datalist> tag from the partial view and placed it in the main view, and used class instead of id. Then I changed my JS to something like this:
$("body").on("keyup", ".projectField", function () {
var self = $(this);
if (globalTimeout !== null) {
clearTimeout(globalTimeout);
}
globalTimeout = setTimeout(function () {
globalTimeout = null;
contractsCall(self.val());
}, delay);
});
This way I can search using my AJAX call for $(this) input box. The other issue I had was seeing which input box was clicked so I can update some other things, for this I used:
document.querySelectorAll('input[list="projectResults"]').forEach(function (element) {
element.addEventListener('input', onInput);
});
Which calls:
function onInput(e) {
var input = e.target,
val = input.value;
list = input.getAttribute('list'),
options = document.getElementById(list).childNodes;
var row = $(this).closest("tr");
var p = row.find(".projDescription");
for (var i = 0; i < options.length; i++) {
if (options[i].value === val) {
$.ajax({
cache: false,
type: "GET",
contentType: "application/json;charset=utf-8",
url: "/ContractProject/GetProjects?query=" + val;
})
.done(function (data) {
if (data[0] !== undefined) {
console.log(data[0]["WorksDescription"]);
p.text(data[0]["WorksDescription"]);
}
});
break;
}
}
}
It's a little bit counter intuitive because I am making 2 AJAX calls but the second one isn't going to be heavy as it's asking for a specific element.

Cascading Dropdown Lists in ASP.NET MVC5

I'm working on creating two dropdown lists for a form. The first is a list of Areas and the second needs to filter to the Job Types based on the selected Area.
I'm basing the majority of my code on this answer, but am having trouble getting the Job Types list to show in the View. I can see the correct options being appended when debugging, but am stuck on why they are not populating the Job Type dropdown list.
The View
<!--Area Dropdown-->
#Html.DropDownList("areas", null , new { #class = "col s12 m6 l3" })
<!--Job Type Dropdown-->
#Html.DropDownList("jobType", Enumerable.Empty<SelectListItem>(), "Job Type", new { #class = "col s12 m6 l3" })
The controller code, which is populating my first dropdown box (Area)
var jobArea = (from a in db.tblJobTypes
where a.Active == true
select a.Department).Distinct().ToList();
ViewData["areas"] = new SelectList(jobArea);
The POST action within the controller
[HttpPost]
public ActionResult JobTypeByArea(string area)
{
var test = (from a in db.tblJobTypes
where a.Active == true && a.Department == area
select new
{
id = a.JobTypeID,
job = a.JobType
}).ToList();
return Json(test, JsonRequestBehavior.AllowGet);
}
And finally, the JQuery
$(document).ready(function () {
$('#areas').change(function () {
$.ajax({
url: '/Home/JobTypeByArea',
type: 'POST',
data: { area: $(this).val() },
datatype: 'json',
success: function (data) {
var options = '';
var category = $('#jobType');
$.each(data, function () {
options += '<option value="' + this.id + '">' + this.job + '</option>';
});
$('#jobType').append(options);
},
});
});
});

Html.DropDownList passing as null using .val() in JSON

I am trying to get the value of an item in a dropdownlist and pass it to the controller using an ajax post, but whatever I pass keeps returning as null.
DropDownList:
<div class="form-inline">
#Html.DropDownList("People", null, new { #id = "personID", #class = "form-control" })
<button onClick="setTimeout( initCalendar, 5000 );" type="button" id="btnInit" data-backdrop="static" data-keyboard="false" data-toggle="modal" href="#loadingModal" class="btn btn-info">Initialise Calendar</button>
</div>
ajax post:
function initCalendar() {
// This function will be executed when you click the element
// show the element you want to show
$("#loadingModal").show();
alert($('#personID').val(""));
//var dataRow = {
// 'ID': $('#personID').val()
//};
var dataRow = $('#personID').val();
console.log(dataRow);
console.log($('#personID').length);
$.ajax({
type: 'POST',
url: "/Event/SelectPerson",
dataType: "json",
contentType: "application/json",
data: JSON.stringify(dataRow)
});
startCalendar();
// Set a timeout to hide the element again
setTimeout(function () {
$('#loadingModal').modal('hide');
}, 5000);
}
Controller:
public ActionResult Index()
{
ViewBag.Hours = GetHoursList();
ViewBag.People = GetPeopleList();
return View();
}
// Finds all people in the database and adds them to a list for a dropdownlist.
public List<SelectListItem> GetPeopleList()
{
List<SelectListItem> peopleList = new List<SelectListItem>();
var people = from s in db.People
select s;
foreach (Person person in people)
{
peopleList.Add(new SelectListItem
{
Text = person.Forename + " " + person.Surname,
Value = person.ID.ToString()
});
}
//var sortedPeopleList = (from person in peopleList
// orderby person.Text
// select person).ToList();
return peopleList;
}
public void SelectPerson(int ID)
{
Person person = db.People.Where(p => p.ID == ID).FirstOrDefault();
Session["Person"] = person;
}
When I log the JSON, the ID is always null and I cant figure out why.
Thanks in advance.
The following line
alert($('#personID').val(""));
is setting the value of the element with id="personID" to null. You need to change it to
alert($('#personID').val());
try this one.
var dataRow = $('#personID').val();

Ajax not appending to my drop down list (C# MVC)

I'm busy with 2 drop downs. The first one is country and loads fine, then on country change I call ajax to populate the province drop down.
The code works fine and when I put an alert in my ajax call it shows the correct data being created but it doesn't append it the drop down so the values aren't available.
Drop Down
<div class="form-group">
<label class="col-md-3 col-xs-5 control-label">Country:</label>
<div class="col-md-9 col-xs-7">
#Html.DropDownListFor(x => x.CountryId, (IEnumerable<SelectListItem>)ViewBag.CountryItems, "Please Select", new { #id = "ddlCountry", #class = "form-control select" })
</div>
</div>
<div class="form-group">
<label class="col-md-3 col-xs-5 control-label">Province:</label>
<div class="col-md-9 col-xs-7">
#Html.DropDownListFor(x => x.ProvinceId, Enumerable.Empty<SelectListItem>(), "Please Select", new { #id = "ddlProvince", #class = "form-control select" })
</div>
</div>
The Ajax
<script>
$('#ddlCountry').change(function () {
var countries = document.getElementById("ddlCountry");
var countryId = countries.options[countries.selectedIndex].value;
$.ajax({
url: "/Master/GetProvinces",
data: { countryId: countryId },
dataType: "json",
type: "GET",
error: function () {
alert(" An error occurred.");
},
success: function (data) {
$.each(data, function (i) {
var optionhtml = '<option value="' + data[i].Value + '">' + data[i].Text + '</option>';
$("#ddlProvince").append(optionhtml);
});
}
});
});
</script>
The code behind
public ActionResult GetProvinces(string countryId)
{
IEnumerable<SelectListItem> ProvinceItems = null;
if (!string.IsNullOrEmpty(countryId))
{
ProvinceItems = BusinessAPI.ProvinceManager.GetAllProvincesByCountryId(Convert.ToInt32(countryId)).Select(ci => new SelectListItem
{
Value = ci.Id.ToString(),
Text = ci.Name
});
}
return Json(ProvinceItems, JsonRequestBehavior.AllowGet);
}
I found the problem.
I have a javascript file in there thats causing some issues.
<script type="text/javascript" src="../../Scripts/js/plugins/bootstrap/bootstrap-select.js"></script>
This came with the template I bought and it helps with the way the dropdowns and stuff works.
With that javascript file you have to add .selectpicker('refresh'); to the append to load it properly like this
$("#ddlProvince").append(optionshtml).selectpicker('refresh');
That might be slow when loading a large amount of data so just refreshing the dropdown once after everything done works well. Here is the code that works well for me now
$('#ddlCountry').change(function () {
var countries = document.getElementById("ddlCountry");
var countryId = countries.options[countries.selectedIndex].value;
$.ajax({
url: "/Master/GetProvinces",
data: { countryId: countryId },
dataType: "json",
async: true,
type: "GET",
error: function () {
alert(" An error occurred.");
},
success: function (data) {
("#ddlProvince").empty();
$.each(data, function (i) {
var optionshtml = '<option value="' + data[i].Value + '">' + data[i].Text + '</option>';
$("#ddlProvince").append(optionshtml);
});
$("#ddlProvince").selectpicker('refresh');
}
});
});

Categories

Resources