I'm trying to create a view which has two DropDownLists. The options available in the second DropDownList depend upon what the user has selected in the first. I'm passing this data to my view in the ViewBag as follows:
List<SelectListItem> firstBoxChoices = ViewBag.firstBoxChoices;
Dictionary<string, List<SelectListItem>> secondBoxDict = ViewBag.secondBoxDict;
The first object has the choices for the first DropDownList. When the user selects one of those, I need to get the appropriate list of choices for the second DropDownList from my Dictionary. I just can't figure out how to achieve this. If I get the new selection of the first DropDownList in a Javascript onchange() function, there doesn't seem to be any way to use this value as the key for my C# dictionary.
Of course, I've seen this functionality on the web so I know it must be possible somehow. How can I achieve this?
Thanks!
There are a couple ways of doing this without forcing you to store all the possible data items in the model, my preference is to use Javascript/JQuery. Here is an example of a Country/State cascading drop down:
Javascript used to get states when a country is selected:
<script type="text/javascript">
function AppendUrlParamTokens(url, params) {
for (var param in params) {
if (params[param] == null) {
delete params[param];
}
}
return url + "?" + jQuery.param(params);
}
function OnCountriesChange(ddl) {
jQuery.getJSON(AppendUrlParamTokens('#Url.Action("GetStates", "Data")', { countryId: ddl.options[ddl.selectedIndex].value }), function (result) {
var target = jQuery('#states_ddl');
target.empty();
jQuery(result).each(function() {
jQuery(document.createElement('option'))
.attr('value', this.Value)
.text(this.Text)
.appendTo(target);
});
});
};
</script>
Country dropdown:
#Html.DropDownListFor(model => model.Country, new SelectList(Model.Countries, "Value", "Text", Model.PreviousCountrySelected), "(Select One)", new { id = "countries_ddl", onchange = "OnCountriesChange(this)" })
State dropdown:
Html.DropDownListFor(model => model.State,
Model.States != null
? new SelectList(Model.States, "Value", "Text", Model.PreviousStateSelected)
: new SelectList(new List<SelectListItem>(), "Value", "Text"),
new { id = "states_ddl" })
Controller method to retrieve states:
public ActionResult GetStates(short? countryId)
{
if (!countryId.HasValue)
{
return Json(new List<object>(), JsonRequestBehavior.AllowGet);
}
var data = GetAllStatesForCountry(countryId.Value).Select(o => new { Text = o.StateName, Value = o.StateId });
return Json(data, JsonRequestBehavior.AllowGet);
}
The idea is that on selection of dropdown 1 you use ajax to go retrieve your second dropdown's value.
Edit: Forgot to include utility method for constructing urls
The .change event of your first select should populate the second select by calling a server method that returns the option data based on the selected value. Given the following view model
public class MyModel
{
[Required(ErrorMessage = "Please select an organisation")]
[Display(Name = "Organisation")]
public int? SelectedOrganisation { get; set; }
[Required(ErrorMessage = "Please select an employee")]
[Display(Name = "Employee")]
public int? SelectedEmployee { get; set; }
public SelectList OrganisationList { get; set; }
public SelectList EmployeeList { get; set; }
}
Controller
public ActionResult Edit(int ID)
{
MyModel model = new MyModel();
model.SelectedOrganisation = someValue; // set if appropriate
model.SelectedEmployee = someValue; // set if appropriate
ConfigureEditModel(model); // populate select lists
return View(model);
}
[HttpPost]
public ActionResult Edit(MyModel model)
{
if(!ModelState.IsValid)
{
ConfigureEditModel(model); // reassign select lists
return View(model);
}
// save and redirect
}
private void ConfigureEditModel(MyModel model)
{
// populate select lists
model.OrganisationList = new SelectList(db.Organisations, "ID", "Name");
if(model.SelectedOrganisation.HasValue)
{
var employees = db.Employees.Where(e => e.Organisation == model.SelectedOrganisation.Value);
model.EmployeeList = new SelectList(employees, "ID",
}
else
{
model.EmployeeList = new SelectList(Enumerable.Empty<SelectListItem>());
}
}
[HttpGet]
public JsonResult FetchEmployees(int ID)
{
var employees = db.Employees.Where(e => e.Organisation == ID).Select(e => new
{
ID = e.ID,
Name = e.Name
});
return Json(employees, JsonRequestBehavior.AllowGet);
}
View
#model MyModel
....
#Html.LabelFor(m => m.SelectedOrganisation)
#Html.DropDownListFor(m => m.SelectedOrganisation, Model.OrganisationList, "-Please select-")
#Html.ValidationMessageFor(m => m.SelectedOrganisation)
#Html.LabelFor(m => m.SelectedEmployee)
#Html.DropDownListFor(m => m.SelectedEmployee, Model.EmployeeList, "-Please select-")
#Html.ValidationMessageFor(m => m.SelectedEmployee)
....
Script
var url = '#Url.Action("FetchEmployees")';
var employees = $('SelectedEmployee');
$('#SelectedOrganisation').change(function() {
employees.empty();
if(!$(this).val()) {
return;
}
employees.append($('<option></option>').val('').text('-Please select-'));
$.getJson(url, { ID: $(this).val() }, function(data) {
$.each(data, function(index, item) {
employees.append($('<option></option>').val(item.ID).text(item.Text));
});
});
});
Related
i'm having trouble while choose each category, it can't show book of each category. My index code here
#using (Html.BeginForm("Index", "BorrowBook", FormMethod.Post, new { name = "demoForm" }))
{
#Html.DropDownList("id_category", (IEnumerable<SelectListItem>)ViewBag.listTest, "-- Select Category --",
new { onchange = "SelectedIndexChanged()" })
<div> Show list of book in the middle </div>
}
And my controller like that
// GET: BorrowBook
public ActionResult Index(string mess)
{
var query = context.categories.Select(c => new { c.id_category, c.name });
var userInfomatiom = (LibraryAsp.Models.User)Session["USER"];
if (userInfomatiom.Role.id_role == 1)
{
ViewBag.listP = publisherDao.getAll();
ViewBag.listC = categoryDao.getAll();
ViewBag.list = bookDao.getAll();
ViewBag.listTest = new SelectList(query.AsEnumerable(), "id_category", "name");
ViewBag.mes = mess;
return View();
}
else
{
return RedirectToAction("Error", "Home");
}
}
[HttpPost]
public ActionResult Index (Category category)
{
ViewBag.listP = publisherDao.getAll();
ViewBag.listC = categoryDao.getAll();
ViewBag.list = context.books.Where(p => p.id_category == category.id_category).ToList();
return View();
}
When debugging, i found that id category, form, or value is loaded like this
But when i choose each category, i get bug like that:
I think my java script is having problem. But i can't figure out this. Any body can help me, many thanks.
Problem solve, my bad to forget pass data. Should be like that
[HttpPost]
public ActionResult Index (Category category)
{
var query = context.categories.Select(c => new { c.id_category, c.name });
ViewBag.listP = publisherDao.getAll();
ViewBag.listC = categoryDao.getAll();
ViewBag.list = context.books.Where(p => p.id_category == category.id_category).ToList();
ViewBag.listTest = new SelectList(query.AsEnumerable(), "id_category", "name");
return View();
}
Here I tried using TempData to pass data from controller action method to partial view. But it does not work.
My Controller Code
public class PropertyController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult GetRequestReport()
{
List<ReportsInfo> reportsList = reportsManager.GetRequestReport(UserName, Locality, "usp_GetResults");
int count = reportsList.Select(x => x.UserId).Distinct().Count();
TempData["Count"] = count;
return PartialView("_Partial1", reportsList);
}
public ActionResult Test(string id)
{
switch (id)
{
case "tab1":
return PartialView("_Results");
case "tab2":
return PartialView("_Results2");
}
return new EmptyResult();
}
}
Index.cshtml
<div id="div-for-partial">
</div>
$(function () {
$('.tab').click(function () {
var id = this.id;
$.get('#Url.Action("Test")', { "id": id }, function (data) {
$('#div-for-partial').html(data);
$('.mvc-grid').mvcgrid();
});
});
});
_Results Partial View
#TempData["Count"]
<br />
<div id="reportList">
#Html.AjaxGrid(Url.Action("GetRequestReport", "Property"))
</div>
_Partial1 Partial View
#model Project.Models.ReportsInfo
#(
Html.Grid(Model)
.Build(columns =>
{
columns.Add(model => model.ApproverName).Titled("Approver Name");
})
.Empty("No records found.")
.Sortable()
.Pageable(pager =>
{
pager.RowsPerPage = 15;
})
)
I have even tried view bag but no luck is there any way to achieve it. Basically I want to pass count of results in TempData and use in partial view
public ActionResult GetRequestReport()
{
List<ReportsInfo> reportsList = reportsManager.GetRequestReport(UserName, Locality, "usp_GetResults");
int count = reportsList.Select(x => x.UserId).Distinct().Count();
ViewData["Count"] = count;
return PartialView("_Partial1");
}
In Partial1 partial View, you can get count in a count variable as shown below and use it where ever you want to.
#(
int count=(int)ViewData["Count"];
Html.Grid(Model)
.Build(columns =>
{
columns.Add(model => model.ApproverName).Titled("Approver Name");
})
.Empty("No records found.")
.Sortable()
.Pageable(pager =>
{
pager.RowsPerPage = 15;
})
)
you never called GetRequestReport() before calling Results partial view, how do you expect to get the value of count passed to Results partial view. Please verify what you are asking.
I'm a novice in javascript, and a junior developper in OOP.
After many attempts and many google search I dind't make it to solve it.
I have a DropDownList and a Partial View. I want to give the selected value to the partial view controller. It works when I write the value directly in, but it doesn't if i try to catch the DropDownList value. For the moment the value returned is always empty.
Model
public partial class Clients
{
public int ClientID { get; set; }
public string Code { get; set; }
public string Nom { get; set; }
public string Adresse1 { get; set; }
public string Adresse2 { get; set; }
public string CP { get; set; }
public string Ville { get; set; }
public Nullable<System.DateTime> DateCreation { get; set; }
public Nullable<System.DateTime> DateModification { get; set; }
}
View
#Html.DropDownList("id", (IEnumerable<SelectListItem>)ViewData["oas"], new { #id = "ClientID" })
<div id="result"></div>
<script>
$(function () {
$('#ClientID').change(function () {
//var pid = $("#id").val();//$(this).data('id');
$('#result').load('#Url.Action("filter")',
{ id: $("#id").val() } //replacing $("#id").val() by "3" makes it work, but i of course don't a constant value here
);
});
});
Controller
public class OnePageController : Controller
{
Entities db = new Entities();
public ActionResult Index()
{
List<SelectListItem> list = new List<SelectListItem>();
list.Add(new SelectListItem { Text = "-Please select-", Value = "Selects items" });
var clts = (
from c in db.Clients
select c).ToArray();
for (int i = 0; i < clts.Length; i++)
{
list.Add(new SelectListItem
{
Text = clts[i].Nom,
Value = clts[i].ClientID.ToString(),
Selected = (clts[i].ClientID == 1)
});
}
ViewData["oas"] = list;
return View(/*db.Clients.ToList()*/);
}
[HttpPost]
public ActionResult Filter(string id)
{
var contact = from c in db.Contacts
where c.ClientID.ToString() == id
select c;
return PartialView(contact);
}
}
Any idea would be greatly appreciated, also i don't know how to debug javasript, i use the developper tools in my when browser to try to catch the values, but i don't really track the changes..
You should change a bit your script:
$(function () {
// You select the element with id = ClientID
var clientEle = $('#ClientID');
// You register an event handler for the change of the selected value
clientEle.change(function () {
// clientEle.val() would return the selected value
$('#result').load('#Url.Action("filter")',{ id: clientEle.val() });
});
});
Regarding how you should debug JavaScript I would suggest to write the following keyword a few lines before you want to start the debugging:
debugger;
Then open developer tools and refresh your page. When JavaScript engine hits the debugger would stop it's execution and from this moment you could examine you code line by line.
For a thorough understanding in how you could debug JavaScript, you could start by checking the following links
https://developers.google.com/web/tools/chrome-devtools/javascript/
https://developer.mozilla.org/en-US/docs/Mozilla/Debugging/Debugging_JavaScript
https://www.w3schools.com/js/js_debugging.asp
I have this code.
The objective of this js is through the dropwdown load the textbox UserMR
But it never finds the UserMR.
I call UserMr model inside Star instantiating a new object.
relationships:
Star contains idModel
Model does not contain IDStar
What is going on?
Model
[CustomValidation(typeof(StarValidation), "DateValidate")]
public partial class Star
{
public virtual string UserMR { get { return this.User.UserMR; } set { this.UserMR = value;} }
public Model User = new Model();
View inside "STAR"
#Html.EditorFor(i => i.IdModel, "StarModel", new { onchange = "updateUserMR($(this))" })
#Html.DisplayFor(i => i.UserMR)
<script type="text/javascript">
function updateUserMR(model) {
var user = model.brother("#Html.NameFor(x => x.UserMR)");
var idModel = model.val();
user.empty();
if (idModel != null && idModel != "")
user.loadOptions("#Url.Action("ListJsonUserMR", "Model")?idModel=" + idModel, true, true);
}
</script>
Controller
public JsonResult ListJsonUserMR(int idModel)
{
var model = this.service.GetUserMr(idModel).Select(x => new
{
Value = x.Id,
Description = x.UserMR
});
return this.Json(model, JsonRequestBehavior.AllowGet);
}
Service
public IEnumerable<Model> GetUser(int idModel)
{
return base.context.Models
.Where(x => x.Id == idModel);
}
Error
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 7 years ago.
Improve this question
I have a small test program in ASP.NET MVC4 which allows you to select items from a dropdown menu. It uses Json and JavaScript (I'm not familiar with these at all).
Here's the code I have at the moment:
HomeController:
public ActionResult CountryList()
{
IQueryable countries = Country.GetCountries();
if (HttpContext.Request.IsAjaxRequest())
{
return Json(new SelectList(
countries,
"CountryCode",
"CountryName"), JsonRequestBehavior.AllowGet
);
}
return View(countries);
}
public ActionResult StateList(string CountryCode)
{
IQueryable states = State.GetStates().Where(x => x.CountryCode == CountryCode);
if (HttpContext.Request.IsAjaxRequest())
return Json(new SelectList(
states,
"StateID",
"StateName"), JsonRequestBehavior.AllowGet
);
return View(states);
}
View:
#section scripts {
<script type="text/javascript">
$(function () {
$.getJSON("/Home/Countries/List", function (data) {
var items = "<option>---------------------</option>";
$.each(data, function (i, country) {
items += "<option value='" + country.Value + "'>" + country.Text + "</option>";
});
$("#Countries").html(items);
});
$("#Countries").change(function () {
$.getJSON("/Home/States/List/" + $("#Countries > option:selected").attr("value"), function (data) {
var items = "<option>---------------------</option>";
$.each(data, function (i, state) {
items += "<option value='" + state.Value + "'>" + state.Text + "</option>";
});
$("#States").html(items);
});
});
});
</script>
}
<h1>#ViewBag.Title</h1>
#using (Html.BeginForm())
{
<label for="Countries">Countries</label>
<select id="Countries" name="Countries"></select>
<br /><br />
<label for="States">States</label>
<select id="States" name="States"></select>
<br /><br />
<input type="submit" value="Submit" />
}
and finally the Models:
Country
public class Country
{
public string CountryCode { get; set; }
public string CountryName { get; set; }
public static IQueryable<Country> GetCountries()
{
return new List<Country>
{
new Country {
CountryCode = "CA",
CountryName = "Canada"
},
new Country{
CountryCode = "US",
CountryName = "United-States"
}
}.AsQueryable();
}
}
}
State:
public class State
{
public string CountryCode { get; set; }
public int StateID { get; set; }
public string StateName { get; set; }
public static IQueryable<State> GetStates()
{
return new List<State>
{
new State
{
CountryCode = "CA",
StateID=1,
StateName = "Ontario"
},
new State
{
CountryCode = "CA",
StateID=2,
StateName = "Quebec"
},
new State
{
CountryCode = "CA",
StateID=3,
StateName = "Nova Scotia"
// .. and so on
}.AsQueryable();
}
}
}
My question is: how do I make this solution work with a database table? What do I need to do in order to make this same dropdown work with fields from a database? Does anyone have any useful tutorials that they could recommend?
You need to choose how you will access your database. There are a lot of options, but I recommend you to use some kind of ORM. It's not easy to choose an ORM too. So you will need to do a research before and find one that fits your needs best. As you wrote in comment you are new to this, so I will provide few samples of how fetching of States might look in different ORM's.
Dapper - ORM used on this (SO) site.
using (var conn = new SqlConnection("CONN_STR"))
{
IList<State> states = conn
.Query<State>(
"select * States where CountryCode = #CountryCode",
new { CountryCode = countryCode })
.ToList();
}
As you can see here we just provide SQL and object with object with parameters and Dapper does all things for us. We get list of entities.
Entity Framework - ORM created by Microsoft.
IList<State> states =
DbContext.States.Where(state => state.CountryCode == countryCode).ToList();
You don't need to write any SQL at all, we are using pure LINQ syntax.
Of course all ORM's has their pros and cons, so again, you need to do a research before.
EDIT: It seems that you have problems with filling selects... Then first you will need to create correct models for EF. You can reuse your existing models, just add some attributes:
[Table("Countries")]
public class Country
{
public string CountryCode { get; set; }
public string CountryName { get; set; }
}
[Table("States")]
public class State
{
[Key]
public int StateID { get; set; }
public string StateName { get; set; }
public string CountryCode { get; set; }
}
In Table attribute you should use your real table names of course. Then you need to create DbContext:
public class MyDbContext : DbContext
{
public DbSet<Country> Countries { get; set; }
public DbSet<State> States { get; set; }
}
Don't forget to specify connection string in web.config like in tutorial.
I simplified methods for getting countries and states and now they return only JSON:
public ActionResult CountryList()
{
using (var db = new MyDbContext())
{
var countries = db.Countries.ToList();
return Json(
new SelectList(countries, "CountryCode", "CountryName"), JsonRequestBehavior.AllowGet);
}
}
public ActionResult StateList(string countryCode)
{
using (var db = new MyDbContext())
{
var states = !string.IsNullOrEmpty(countryCode)
? db.States.Where(state => state.CountryCode == countryCode).ToList()
: new List<State>();
return Json(
new SelectList(states, "StateID", "StateName"), JsonRequestBehavior.AllowGet);
}
}
It's a good idea to move DB access code to different class but I hope you can do it yourself.
You had some strange URl's in you javascript so here is working example:
$.getJSON("/Home/CountryList", function (data) {
// Same code that you have
});
$("#Countries").change(function () {
$.getJSON("/Home/StateList?countryCode=" + $("#Countries > option:selected").attr("value"), function (data) {
// Same code that you have
});
});
If you need to get the list of countries or states from a database then what you need to do is be able to query the database. See these examples of using ado.net to query a database. https://msdn.microsoft.com/en-us/library/vstudio/dw70f090%28v=vs.100%29.aspx
Then just change your .GetCountries and GetStates to get the list from the database. The code will look something like this (this is just pseudocode)
var List<States> l = new List<States>();
while(reader.read()){
var s = new State{
CountryCode = reader["cc_code"],
StateID=reader["stateId"],
StateName = reader["stateName"]
};
l.add(s);
}
return l;