I am developing an MVC 4 web application. One of the Razor views has two drop down lists. The first drop down list is populated by the ViewModel data which is passed to the view. The secondary drop down list is populated using a JQuery and Ajax call based on the selected ID from the first drop down list (cascading).
I have this working fine, however, whenever a user wishes to edit an existing record I can't get the selected secondary drop down list value to be selected.
This is my Razor code for the two drop down lists
<div class="lbl_a">
Employer:
</div>
<div class="editor-field sepH_b">
#Html.DropDownListFor(model => model.Employer, Model.EmployerList, "Select", new { #class = "inpt_a" })
</div>
<div class="editor-label">
#Html.LabelFor(model => model.DirectorateID, "Directorate/ Service Group")
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.DirectorateID, Model.DirectorateList, "Select")
</div>
This is my JQuery code
$(document).ready(function () {
//Pre load on page load
onEmployerChange();
//Hide and show DIVS based on selection
$("#Employer").change(onEmployerChange);
function onEmployerChange() {
var dataPost = { orgID: val };
$.ajax({
type: "POST",
url: '/User/GetDirectorates/',
data: dataPost,
dataType: "json",
error: function () {
alert("An error occurred." + val);
},
success: function (data) {
var items = "";
$.each(data, function (i, item) {
items += "<option value=\"" + item.Value + "\">" + item.Text + "</option>";
});
$("#DirectorateID").html(items);
}
});
}
}
});
When a user selects a value from the first drop down list, the selected ID is passed to the GetDirectorates action within the User Controller.
This is my GetDirectorates action which returns Json data
public ActionResult GetDirectorates(string orgID)
{
if (String.IsNullOrWhiteSpace(orgID))
orgID = "0";
var Directorates = _ListService.GetListItemsByOrganisationID(Convert.ToInt32(orgID));
List<SelectListItem> directorateList = new List<SelectListItem>();
directorateList.Add(new SelectListItem() { Text = "Select", Value = "" });
foreach (var directorate in Directorates)
{
directorateList.Add(new SelectListItem() { Text = directorate.description, Value = directorate.listItemID.ToString(), Selected = false });
}
return Json(new SelectList(directorateList, "Value", "Text"));
}
Whenever the users wishes to edit an existing record I pass both the values for the first and second drop down list. Both drop down lists are populated with the proper data as expected, however, the selected value for the second drop down list is never selected.
This is a shortened version of the Edit action which the user calls when attempting to edit an existing record but shows the two drop down list selected values being passed.
public ActionResult EditNonMember(int id, string feedback, string courseDateID, string courseID)
{
//code to retrieve data here
vm.Employer = UserDetails.Employer;
vm.DirectorateID = UserDetails.DirectorateID;
return View(vm);
}
Would anyone be able to help me with this?
Thanks.
You need to get the directorate list for the saved employer id and set the DirectorateList collection and then the DirectorateID (from saved record);
public ActionResult EditNonMember(int id, string feedback, string courseDateID,
string courseID)
{
//code to retrieve data here
var userDetails=repositary.GetUserFromSomeId(id);
vm.Employers=GetEmployers();
vm.Employer = userDetails.Employer;
vm.DirectorateList=GetDirectorateListForEmployer(userDetails.Employer);
vm.DirectorateID = userDetails.DirectorateID;
return View(vm);
}
private List<SelectListItem> GetEmployers()
{
// to do : Return all employers here in List<SelectListItem>
}
private List<SelectListItem> GetDirectorateListForEmployer(int employerId)
{
// to do : Return all Directorates for the selected employer
}
This should do the trick:
var subSelect = $("#DirectorateID");
// clear the selection
subSelect.empty();
//append each option to the list
$.each(data, function (i, item) {
subSelect.append($('<option/>', {
value: item.Value,
text: item.Text
}));
});
Rather than setting it via the html method, I'm simply appending an option.
This is the method I use for cascading dropdown lists using ajax.
Related
I have a #Html.DropDownList on my view whose initial values are null. The values of the list must be populated based on the selected value from an other dropDownList. I have my two dropDownLists as below
<div class="col-sm-7">
#Html.DropDownList("City", null, new {#id="City", #class="form-control"})
</div>
<div class="col-sm-7">
#Html.DropDownList("Theatre", null, new {#id = "Theatre", #class = "form-control"})
</div>
Theatre must be populated based on the value selected in the dropDown list for city. As Theatre cannot be null, I initially set the ViewBag.Theatre to an empty list in my controller's action method. Once a city is selected, I am doing an ajax call from jQuery to call a different method in my controller to set the ViewBag.Theatre to my returned list.
But the contents of the Theatre dropDown are still empty. How do I refresh the contents of the dropDown after the ViewBag.Theatre value is changed?
Here is my jQuery to call the controller method
$("#City").change(function() {
if ($("#City").val() != 0) {
var ty = $("#City").val();
$.ajax({
url: rootDir + "/AnalysisHistory/SetTheatres",
data: {city: city },
type: "POST",
dataType: "html",
success: function () {
$(".form").show();
$("#loading").hide();
$("#analysisDetails").slideDown('slow');
});
} else {
$(".form").hide();
}
});
On change for the dropdown list for the city, here is what I did to populate the theaters drop down:
•I emptied the contents of the dropdown list for the theaters
•As I am receiving the new list as a JSON, on Success, I am re-populating the list with new contents. Here is my code
success: function (datax) {
var result = "";
var listObj = $.parseJSON(datax);
$(listObj).each(function (i, val) {
result += '<option value="' + val.Value + '">' + val.Text + '</option>';
});
$("#Theatre").html(result);
$(".form").show();
$("#loading").hide();
$("#analysisDetails").slideDown('slow');
}
I have dropdown list which was created dynamically like:
#for(int i=0;i<=count;i++)
{
#Html.DropDownListFor(m => m.GetTimeSheetDetails[i].PROJ_ID, (SelectList)ViewBag.ProjectList, "-- Choose a Project --", new { #class = "ddlProjectvalue" })
}
<input type="submit" value="Add Record" name="btn"/>
in Contoller I am loading data to dropdownlist:
[HttpPost]
Public ActionResult Timesheet()
{
TimsheetModel model=new TimesheetModel();
if(btn=="Add Record")
{
var data= Session["ddlData"] as IEnumerable<SelectListItem>;
SelectList list1=new SelectList(data,"Value","Text",model.ProjID);
ViewBag.ProjectList=list1;
count++; // ADDS NEW RECORD
return View();
}
else
{
var result = (from proj in db.PROJECTs where proj.IS_DELETED == "N" select new { Value = proj.ID, Text = proj.NAME })
SelectList list = new SelectList(result, "Value", "Text", tm.PROJ_ID);
ViewBag.ProjectList = list;//Data loaded here for Dropdown list
}
return View();
}
Now My Scenario is if count=5 which means if we have five dropdown lists, when I select item in first dropdown list should not show in second dropdown list and if we have select item in second dropownlist should not show items of first and second in third dropdown list. for that I have written script like:
<script>
$(document).ready(function () {
$('.ddlProjectvalue').change(function () {
var id = $('.ddlProjectvalue').attr('id');
var selector = "#" + id;
var selectedValue = $(this).val();
$.ajax({
url: "#Url.Action("GetDDLData","Employer")",
data: { selectedValue: selectedValue, id: id },
dataType: "json",
type: "GET",
error: function () {
alert(" An error occurred.");
},
success: function (data) {
debugger;
$("" + selector + "").removeClass("ddlProjectvalue");
$('.ddlProjectvalue').empty();
var optionhtml1 = '<option value="' +
0 + '">' + "--Choose a Project--" + '</option>';
$(".ddlProjectvalue").append(optionhtml1);
$.each(data, function (i) {
var optionhtml = '<option value="' +
data[i].Value + '">' + data[i].Text + '</option>';
$(".ddlProjectvalue").append(optionhtml);
});
}
});
});
});
</script>
and when i pass selected value to controller like:
public ActionResult GetDDLData(string selectedValue, string id, string addrecord)
{
int projectid = Convert.ToInt32(selectedValue);
if (id == "GetTimeSheetDetails_0__PROJ_ID")
{
IEnumerable<SelectListItem> projectslist = (from proj in db.PROJECTs where proj.IS_DELETED == "N" && proj.ID != projectid select proj).AsEnumerable().Select(projt => new SelectListItem() { Text = projt.NAME, Value = projt.ID.ToString() });
var result = new SelectList(projectslist, "Value", "Text", tm.PROJ_ID).ToList();
Session["ddlData"] = result;
ViewBag.ProjectList = result;
return Json(result, JsonRequestBehavior.AllowGet);
}
else
{
var result = Session["ddlData"] as IEnumerable<SelectListItem>;
var query = (from data in result where data.Value != selectedValue select data) as IEnumerable<SelectListItem>;
Session["ddlData"] = query;
return Json(result, JsonRequestBehavior.AllowGet);
}
}
Now my problem is when I add new record by clciking on Add button, loading Session["ddldata"] data to total dropdown list instead it should remain selectlist item in first dropdownlist for first time, I need like when i first select a dropdownlist item in first dropdown list it should remain same when add record also. it means i should prevent server side load on first select list item and vice versa.
Note: Due to some issues i should add record on server side only
How I can prevent it, I tried like preventDefault or return false using jquery, but not working, Any Ideas? how can I fix it.
I think you are overcomplicating things here. You don't really need to request new options from server. Why not just filter the option out on the javascript side?
$(document).ready(function() {
$('.ddlProjectvalue').change(function() {
updateDDLValues();
});
updateDDLValues();
});
function updateDDLValues() {
// Display all
$('.ddlProjectvalue option').show();
// Hide all selected options from other selectlists
$('.ddlProjectvalue').each(function(i,element) {
var selectedvalue = $(element).find('option:selected').val();
$('.ddlProjectvalue').not(element).find('option[value="'+selectedvalue+'"]').hide();
});
}
Fiddle:
http://jsfiddle.net/Pt7qV/2/
Update:
As for the serverside part of your question, there are some serious flaws in your code. You increase the count property in your controller and use the variable clientside. First you'd think that's how it's done but nope it doesn't work that way.
You are returning View when Add Record is submitted but you aren't returning any model with it.
Your TimsheetModel would look something like this:
public class TimsheetModel
{
public int Count {get; set;}
}
In your controller you pass this to the view:
TimsheetModel model=new TimesheetModel();
if(btn=="Add Record")
{
var data= Session["ddlData"] as IEnumerable<SelectListItem>;
SelectList list1=new SelectList(data,"Value","Text",model.ProjID);
ViewBag.ProjectList=list1;
model.Count++; // ADDS NEW RECORD
return View(model);
}
And in your view:
#model TimsheetModel
#for(int i=0;i<=Model.Count;i++)
{
#Html.DropDownListFor(m => m.GetTimeSheetDetails[i].PROJ_ID, (SelectList)ViewBag.ProjectList, "-- Choose a Project --", new { #class = "ddlProjectvalue" })
}
<input type="submit" value="Add Record" name="btn"/>
I'd suggest you to go back to tutorials or books a bit, this is quite basic stuff after all. I won't go into how you are going to handle database side etc. since I think this answer would just escalate into explaining basic stuff.
I am attempting to create a cascading dropdown with MVC3. The parent dropdown is called "Category", when the user selects a Category, a child dropdown is then populated with a list of pictures that belong to that Category. I've got some code in place right now, and I am able to call the controller from the View when the user selects a category. Here is my code:
Controller:
public ActionResult Pictures(int catId)
{
var k = ((List<Picture>) ViewBag.AllPictures)
.FindAll(x => x.CategoryId == catId)
.Select(x => new
{
Value = x.PictureId,
Text = x.Title
});
return Json(k, JsonRequestBehavior.AllowGet);
}
View:
<div class="editor-field">
#Html.DropDownListFor(model => model.Picture.PictureId, Enumerable.Empty<SelectListItem>(), new { #id = "pictureFilter" })
#Html.ValidationMessageFor(model => model.Picture.PictureId)
</div>
Javascript:
<script type="text/javascript">
$('#ddlFilter').on("change", function() {
var selectedCat = $(this).val();
$.getJSON("/StoreManager/Pictures", { catId: selectedCat }, function(pictures) {
var picturesSelect = $('#pictureFilter');
picturesSelect.empty();
$.each(pictures, function(index, picture) {
picturesSelect.append($('<option/>', {
value: picture.val,
text: picture.text
}));
});
});
});
</script>
When I take a look at variable 'k', that my controller is returning. It does contain all the correct collection items for the pictures, with their respective 'value' and 'text' fields assigned. When it returns the JSON back to the View, it creates a dropdown menu with the exact number of fields that should be there, but they all contain empty data. When I inspect the element in Chrome, here is the HTML afterwards:
<option><option/>
<option><option/>
<option><option/>
<option><option/>
All help is appreciated. Any further code requested will be linked to in pastebin posts.
You have return JSON then you need to used same variables as you send from Pictures controller.
try this:
<script type="text/javascript">
$('#ddlFilter').on("change", function() {
var selectedCat = $(this).val();
$.getJSON("/StoreManager/Pictures", { catId: selectedCat }, function(pictures) {
var picturesSelect = $('#pictureFilter');
picturesSelect.empty();
$.each(pictures, function(index, picture) {
picturesSelect.append($('<option/>', {
value: picture.Value,
text: picture.Text
}));
});
});
});
</script>
or you can also check the response variable get from your Action method by using firebug console tab.
I am having some difficulty figuring out how to return the selected item in my HTML.DropDownList so that upon hitting a submit button, the selected item text will be looked up in my database. Here is what I have:
#{
var selectStaff = "Select LastName + ', ' + FirstName AS Name, StaffID From StaffList ORDER BY LastName";
var data = db.Query(selectStaff);
var items = data.Select(i => new SelectListItem {
Text = i.Name
});
}
And then in the html..
#Html.DropDownList("Select1", items)
This works fine, as my dropdownlist is appearing and is populated, but now upon hitting a submit button, I want to be able to search that text of the selected item in my database. How would I go about doing this?
If you don't bind the dropdown to a property on your view model (which would be preferable), you can still get it simply using Request.Form["Select1"] in your controller action.
If you mean that you want to be able to get the value while still on the razor page, you need to use jQuery (or other javascript) to get the value.
To get the value with jQuery:
$(document).ready(function () {
$("#YourSubmitButtonID").click(function () {
// Get the value from 'Select1'
var value = $("#Select1").val();
});
});
To do something with the value, you would have to use an ajax function, something like this:
$.ajax({
url: '#Url.Action("ActionName", "ControllerName")',
data: { valueToQuery: $("#Select1").val() },
success: function (data) {
// The data is the result
}
});
On the controller named ControllerName in this example, you'd have the code that queries the database and returns your result.
public ActionResult ActionName(string valueToQuery)
{
// Do your stuff here
return Json("your result", , JsonRequestBehavior.AllowGet);
{
I have also found THIS very interesting that May help you out!
You may also try the following Steps if you don't want to use Ajax or Json tactics:
var sql = "SELECT ProductId, ProductName FROM Products";
var data = Database.Open("Northwind").Query(sql);
var items = data.Select(i => new SelectListItem {
Value = i.ProductId.ToString(),
Text = i.ProductName
});
#Html.DropDownList("productid", items)
And Also:
var sql = "SELECT ProductId, ProductName FROM Products";
var data = Database.Open("Northwind").Query(sql);
<select name="productid">
#foreach(var row in data){
<option value="#row.ProductId">#row.ProductName</option>
}
</select>
I am having two tables namely State and Country.These two are dropdowns in my view page.
I am displaying dropdown values of each of them using an independent query.
In table State i am having stateid and countryid.
I need to filter state values based on country selection.
And i even have a main table called Table which consists of ids of both state and country
The following is the way i used to display,
enter code here
//To get state values
var query = (from i in dbContext.countries
join j in dbContext.States on i.Country_id equals j.Country_id
where j.State_id >= 0
select new
{
state = j.State_name}).ToArray//To get state values
enter code here
var str = (from li in dbContext.countries
where li.Country_id >= 1
select new
{
country = li.Country_name}).ToArray();//To get country
values
And how can i query be for filtering the values usin main table "table".i am facing problem in writing query for filtering
Is this possible using linq query ?
Please suggest me how to do this
Thanks
This can be accomplished in different ways. One way is to get the server to return a filtered list of valid options via Ajax when the first dropdown is changed.
For example, assume this scenario: a View with two DropDownLists; one with countries and the other with states. The DropDownList with states is empty and disabled by default until a country is selected.
So you could have this Action in your controller:
public ActionResult Index()
{
ViewBag.Country = new [] {
new SelectListItem() { Text = "Venezuela", Value = "1" },
new SelectListItem() { Text = "United States", Value = "2" }
};
return View();
}
And this View:
<div class="editor-field">
#Html.DropDownList("Country")
#Html.DropDownList("State", Enumerable.Empty<SelectListItem>(), "States", new { #disabled = "disabled" })
</div>
Now add a POST action in your controller. It receives the ID of the selected country and returns JSON containing a filtered list of states:
[HttpPost]
public ActionResult StatesByCountry(int countryId)
{
// Filter the states by country. For example:
var states = (from s in dbContext.States
where s.CountryId == countryId
select new
{
id = s.Id,
state = s.Name
}).ToArray();
return Json(states);
}
The last thing is the client-side code. This example uses jQuery and sets up a change event listener on the country dropdown which calls the new controller action via Ajax. It then uses the returned values to update the 'State' DropDownList.
$(document).ready(function () {
$('#Country').change(function () {
$.ajax({
url: '/Home/StatesByCountry',
type: 'POST',
data: { countryId: $(this).val() },
datatype: 'json',
success: function (data) {
var options = '';
$.each(data, function () {
options += '<option value="' + this.id + '">' + this.state + '</option>';
});
$('#State').prop('disabled', false).html(options);
}
});
});
});