Dynamic state city drop down list in mvc using jquery - asp.net-mvc

i am adding values to 2 dropdownlists dynamically ,to the state dropdownlist it is populated during form load and to the city it must be populated when the jquery fires out when the user clicks on any state,the problem i am facing is that,the state dropdownlist is easily populated but the city dropdownlist does not contain any values when i select a particular state,
the state and city are strings stored in a table in my db
i ll post my code below so that if anyone can sort out what is wrong with my code
homecontroller
public ActionResult registration()
{
ViewBag.states = dd.tb_statecities.Select(m => new SelectListItem { Text=m.state}).Distinct().ToList();
return View();
}
public ActionResult get(string state)
{
var v = (dd.tb_statecities.Where(m => m.state == state).Select(m => m.city)).ToList();
return Json(v, JsonRequestBehavior.AllowGet);
}
jquery..
$(function () {
$('#states').change(function () {
var val = $('#states').val();
$.get("home/get", { state: val }, function (data) {
var v = "<option>Select</option>"
$.each(data, function (i, q) {
alert("hello");
v += "<option value=" + q + ">" + q + "</option>";
});
$('#city').html(v);
});
});
});
registration.cshtml
State #Html.DropDownList("states","Select")
</tr>
<tr class="t">
<td>City</td>
<td>#Html.DropDownList("city", new List<SelectListItem> { new SelectListItem{Text="Select",Value="0"}})</td>
</tr>

The problem is you didn't send value/id when you use ViewBag,
I suggest you use SelectList in your ViewBag :
ViewBag.states = new SelectList(db.states, "ID", "states");
Then you can get the value from using JQuery :
var val = $('#states').val();

Related

MVC Pass IDs from view to controller from checkbox multiselection

At the moment i have a table with a column fill with checkbox for each ID user. and i want to pass that value from checkbox checked from view to controller to perfom some action in actionresult CreatePlanning.
How can i do it ?
<td data-field="#Html.DisplayNameFor(model => model.Status_Coordinator)">
#Html.DisplayFor(model => item.Status_Coordinator)
<input id="Status_Coordinator" type="checkbox" name="Status_Coordinator" value="true" />
</td>
There are probably other ways to do this, but I have done it like this previously - Create a new Checkbox class like:
public class CheckboxModel
{
//Value of checkbox
public int Value { get; set; }
//description of checkbox
public string Text { get; set; }
//whether the checkbox is selected or not
public bool IsChecked { get; set; }
}
Initialise static list of users, to give you an idea (you probably have to generate it dynamically):
ListOfUserID = new List<CheckboxModel>
{
new CheckboxModel { Value = 1, Text = "User1" },
new CheckboxModel { Value = 2, Text = "User2" },
new CheckboxModel { Value = 3, Text = "User3" }
};
Use this class in the view (for example in a loop):
#Html.CheckBoxFor(m => Model.ListOfUserID[i].IsChecked)#Model.ListOfUserID[i].Text
#Html.HiddenFor(m => Model.ListOfUserID[i].Value)
#Html.HiddenFor(m => Model.ListOfUserID[i].Text)
Then you have the text or value of the checkbox in Controller action when the form is posted.
To select use Checkboxfor
`
Select your Order:
#foreach (var x in Model)
{
#Html.CheckBoxFor(modelItem => x.isSelected, new { #id="test"
,value = (x.Orderumber) })
}
Get Values
To pass value To the controller use JQuery as:
<script>
$(document).ready(function () {
$("#b1").click(function () {
var favorite = [];
$.each($("input[name='x.isSelected']:checked"), function () {
favorite.push($(this).val());
});
alert("Your order are: " + favorite.join(", "));
window.location.replace("https://localhost:44304/SecondPage/?
id="+favorite.join(", "));
});
});
</script>

using multiple checkboxes in MVC and saving their values in database

I have added a code to fetch values from a database to show multiple checkboxes as shown below on my view page
#{
var dept_list = ViewBag.department_list;
}
#foreach (var dept_item in dept_list)
{
<input type="checkbox" id="dept_checkbox" name="#dept_item.name" value="#dept_item.department_ID" />
<span class="rmargin20">#dept_item.name</span>
}
Now I want to get the values of the checked checkboxes, and want to save these values to the database. The above mentioned code will generate the checkboxes for each record in database.
This can be done in asp.net. But i want to implement this feature in MVC.
Hi You can use FormCollection for getting the form values..
see my below sample code :
public ActionResult MethodName(FormCollection form)
{
string CheckboxValue = form.Get("CheckBoxName_1"); //Dynamic checkbox name
return View();
}
Hope it helps you :)
if your view is strongly binds then just submit the form and get the checked value using above solution.
And if it is not then using jquery to save checked values.
use a class for each check box
<input type="checkbox" id="dept_checkbox" class="checkbox_dept" name="#dept_item.name" value="#dept_item.department_ID" />
<span class="rmargin20">#dept_item.name</span>
Now get checked values
var selectedDepts == null;
$('.checkbox_dept::checked').each(function (e) {
selectedDepts += this.value + "^";
});
//ajax call
$.post("../ControlerName/Save", { "strSelectedDepts": selectedDepts },
function (data) {
//saved successfully
}.fail(function (xhr, textStatus, errorThrown) {
//Error occured
});
in your controller file.
[HttpPost]
public string Save(string strSelectedDepts)
{
//remove last ^ char
string strData = strSelectedDepts.Substring(0, strSelectedDepts.Length - 1);
string[] arrData = strData.Split('^');
foreach(var itm in arrData)
{
//do save operation
}
}

Displaying values in ListBox based on Dropdoown values

In my view I have one dropdown Role and second ListBox as Permissions. I want to change the values in ListBox as User selects the values in Dropdown Role
<tr>
<td>#Html.Label("","Role")</td>
<td>#Html.DropDownListFor(x => x.Role, #ViewBag.role as SelectList, new { #class = "dropdown"} )</td>
</tr>
<tr>
<td>#Html.Label("","Permissions in Role")</td>
<td>#Html.ListBox("permissions", #ViewBag.permissions as SelectList, new { #class = "chosen-select", data_placeholder = "Add Permissions to Role...", style = "width:500px;", tabindex = "4"})</td>
</tr>
In My js file (Updated After Stephen Suggestion)
$(document).on('change', '#Role_RefID', function () {
var selection = $(this).val();
$.getJSON(window.location.pathname + "/getPermissions?id="+selection, function (result) {
var ddl = $('#permissions');
ddl.empty().trigger("chosen:updated");
$(result).each(function () {
$(document.createElement('option'))
.attr('value', this.Id)
.text(this.Value)
.appendTo(ddl)
.attr('selected',"selected")
;
});
ddl.trigger("chosen:updated");
});
});
getPermissions (Updated after Stephen Suggestion)
public JsonResult getPermissions(int id)
{
List<Reference> perms = rep.permsInRole(id);
var res = perms.Select(p => new { Id = p.RefID, Value = p.Description }).Distinct().ToList();
return Json(res, JsonRequestBehavior.AllowGet);
}
ListBox displays the initial values from DB but when I change the values in dropdown It doesnt clear the contents of Listbox and also doesnt display the new values in ListBoxListBox

ASP.NET Mvc Dropdownlist?

script
$(document).ready(function () {
$("#musteri_sno").change(function () {
var strSayacID = "";
strSayacID = $(this)[0].value; // get the selected state id
var url = "/SayacOkumalari/MusteriSayaclariniGetir/" + strSayacID ;
// call controller's action
$.getJSON(url, null, function (data) {
// do something once the data is retrieved
$("#sayac_no").empty();
$.each(data, function (index, optionData) {
$("#sayac_no").append("<option value='"
+ optionData.sno
+ "'>" + optionData.sayac_seri_no
+ "</option>");
});
});
})
.change(); // making sure the event runs on initialization for default value
});
html
<td>
#Html.DropDownList("musteri_sno", (SelectList)ViewBag.musteri_id, "--Müşteri Seçiniz--", new { id = "musteri_sno" })
</td>
<td>
#Html.DropDownList("sayac_no", Enumerable.Empty<SelectListItem>(), "-- Sayaç Seçiniz --", new { id = "sayac_no" })
</td>
action
[HttpGet]
public ActionResult MusteriSayaclariniGetir(int musteri_sno)
{
var sites = entity.TblSayaclar.Where(x => x.musteri_id == musteri_sno).Select(x => new { sno = x.sno, sayac_seri_no = x.seri_no });
return Json(sites, JsonRequestBehavior.AllowGet);
}
When I removed parameter musteri_no from MusteriSayaclariniGetir(int musteri_sno) action, my codes work correctly. Is there a problem with url var url = "/SayacOkumalari/MusteriSayaclariniGetir/" + strStateID; or different error?
Thanks.
It's a problem of your routing. Use "id" instead of "musteri_sno" to use the default map or add one more routing map for your controller in Global.asax.cs

Cascading drop-downs in MVC 3 Razor view

I am interested in how to implement cascading dropdown lists for addresses in a Razor view. My Site entity has a SuburbId property. Suburb has a CityId, and City has ProvinceId. I would like to display dropdowns for all of Suburb, City, and Province on the Site view, where e.g. the suburb dropdown will initially display "First select a City", and the City dropdown, "First select a province". On selecting a province, cities in the province are populated etc.
How can I achieve this? Where do I start?
Let's illustrate with an example. As always start with a model:
public class MyViewModel
{
public string SelectedProvinceId { get; set; }
public string SelectedCityId { get; set; }
public string SelectedSuburbId { get; set; }
public IEnumerable<Province> Provinces { get; set; }
}
public class Province
{
public string Id { get; set; }
public string Name { get; set; }
}
Next a controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyViewModel
{
// TODO: Fetch those from your repository
Provinces = Enumerable.Range(1, 10).Select(x => new Province
{
Id = (x + 1).ToString(),
Name = "Province " + x
})
};
return View(model);
}
public ActionResult Suburbs(int cityId)
{
// TODO: Fetch the suburbs from your repository based on the cityId
var suburbs = Enumerable.Range(1, 5).Select(x => new
{
Id = x,
Name = "suburb " + x
});
return Json(suburbs, JsonRequestBehavior.AllowGet);
}
public ActionResult Cities(int provinceId)
{
// TODO: Fetch the cities from your repository based on the provinceId
var cities = Enumerable.Range(1, 5).Select(x => new
{
Id = x,
Name = "city " + x
});
return Json(cities, JsonRequestBehavior.AllowGet);
}
}
And finally a view:
#model SomeNs.Models.MyViewModel
#{
ViewBag.Title = "Home Page";
}
<script type="text/javascript" src="/scripts/jquery-1.4.4.js"></script>
<script type="text/javascript">
$(function () {
$('#SelectedProvinceId').change(function () {
var selectedProvinceId = $(this).val();
$.getJSON('#Url.Action("Cities")', { provinceId: selectedProvinceId }, function (cities) {
var citiesSelect = $('#SelectedCityId');
citiesSelect.empty();
$.each(cities, function (index, city) {
citiesSelect.append(
$('<option/>')
.attr('value', city.Id)
.text(city.Name)
);
});
});
});
$('#SelectedCityId').change(function () {
var selectedCityId = $(this).val();
$.getJSON('#Url.Action("Suburbs")', { cityId: selectedCityId }, function (suburbs) {
var suburbsSelect = $('#SelectedSuburbId');
suburbsSelect.empty();
$.each(suburbs, function (index, suburb) {
suburbsSelect.append(
$('<option/>')
.attr('value', suburb.Id)
.text(suburb.Name)
);
});
});
});
});
</script>
<div>
Province:
#Html.DropDownListFor(x => x.SelectedProvinceId, new SelectList(Model.Provinces, "Id", "Name"))
</div>
<div>
City:
#Html.DropDownListFor(x => x.SelectedCityId, Enumerable.Empty<SelectListItem>())
</div>
<div>
Suburb:
#Html.DropDownListFor(x => x.SelectedSuburbId, Enumerable.Empty<SelectListItem>())
</div>
As an improvement the javascript code could be shortened by writing a jquery plugin to avoid duplicating some parts.
UPDATE:
And talking about a plugin you could have something among the lines:
(function ($) {
$.fn.cascade = function (options) {
var defaults = { };
var opts = $.extend(defaults, options);
return this.each(function () {
$(this).change(function () {
var selectedValue = $(this).val();
var params = { };
params[opts.paramName] = selectedValue;
$.getJSON(opts.url, params, function (items) {
opts.childSelect.empty();
$.each(items, function (index, item) {
opts.childSelect.append(
$('<option/>')
.attr('value', item.Id)
.text(item.Name)
);
});
});
});
});
};
})(jQuery);
And then simply wire it up:
$(function () {
$('#SelectedProvinceId').cascade({
url: '#Url.Action("Cities")',
paramName: 'provinceId',
childSelect: $('#SelectedCityId')
});
$('#SelectedCityId').cascade({
url: '#Url.Action("Suburbs")',
paramName: 'cityId',
childSelect: $('#SelectedSuburbId')
});
});
Thanks Darin for your lead to the solution. It greatly helped me to arrive to the point. But as 'xxviktor' mentioned, I did got circular ref. error. To get rid of it, I've done this way.
public string GetCounties(int countryID)
{
List<County> objCounties = new List<County>();
var objResp = _mastRepo.GetCounties(countryID, ref objCounties);
var objRetC = from c in objCounties
select new SelectListItem
{
Text = c.Name,
Value = c.ID.ToString()
};
return new JavaScriptSerializer().Serialize(objRetC);
}
And to achieve auto cascading, I've slightly extended jQuery extension this way.
$('#ddlCountry').cascade({
url: '#Url.Action("GetCounties")',
paramName: 'countryID',
childSelect: $('#ddlState'),
childCascade: true
});
And the actual JS is using this parameter as below (inside JSON request).
// trigger child change
if (opts.childCascade) {
opts.childSelect.change();
}
Hope this helps someone with similar issue.
be aware, that this solution doesn't work directly with EF 4.0. It causes "A circular reference was detected while serializing..." error. Here are possible solutions http://blogs.telerik.com/atanaskorchev/posts/10-01-25/resolving_circular_references_when_binding_the_mvc_grid.aspx , I've used second one.
To implement cascading drop down lists that support MVC's built in validation and binding, you will need to do something a little different than what is done in the other answers here.
If your model has validation, this will support it. An excerpt from a model with validation:
[Required]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public Guid cityId { get; set; }
In your controller you need to add a get method, so that your view will be able to get the relevant data later:
[AcceptVerbs(HttpVerbs.Get)]
public JsonResult GetData(Guid id)
{
var cityList = (from s in db.City where s.stateId == id select new { cityId = s.cityId, name = s.name });
//simply grabbing all of the cities that are in the selected state
return Json(cityList.ToList(), JsonRequestBehavior.AllowGet);
}
Now, to the View that I mentioned earlier:
In your view you have two drop downs similar to this:
<div class="editor-label">
#Html.LabelFor(model => model.stateId, "State")
</div>
<div class="editor-field">
#Html.DropDownList("stateId", String.Empty)
#Html.ValidationMessageFor(model => model.stateId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.cityId, "City")
</div>
<div class="editor-field">
#*<select id="cityId"></select>*#
#Html.DropDownList("cityId", String.Empty)
#Html.ValidationMessageFor(model => model.cityId)
</div>
The content in the drop downs are bound by the controller, and are automatically populated. Note: in my experience removing this binding and relying on java script to populate the drop downs make you lose validation. Besides, the way we are binding here plays nice with validation, so there is no reason to change it.
Now onto our jQuery plugin:
(function ($) {
$.fn.cascade = function (secondaryDropDown, actionUrl, stringValueToCompare) {
primaryDropDown = this; //This doesn't necessarily need to be global
globalOptions = new Array(); //This doesn't necessarily need to be global
for (var i = 0; i < secondaryDropDown.options.length; i++) {
globalOptions.push(secondaryDropDown.options[i]);
}
$(primaryDropDown).change(function () {
if ($(primaryDropDown).val() != "") {
$(secondaryDropDown).prop('disabled', false); //Enable the second dropdown if we have an acceptable value
$.ajax({
url: actionUrl,
type: 'GET',
cache: false,
data: { id: $(primaryDropDown).val() },
success: function (result) {
$(secondaryDropDown).empty() //Empty the dropdown so we can re-populate it
var dynamicData = new Array();
for (count = 0; count < result.length; count++) {
dynamicData.push(result[count][stringValueToCompare]);
}
//allow the empty option so the second dropdown will not look odd when empty
dynamicData.push(globalOptions[0].value);
for (var i = 0; i < dynamicData.length; i++) {
for (var j = 0; j < globalOptions.length; j++) {
if (dynamicData[i] == globalOptions[j].value) {
$(secondaryDropDown).append(globalOptions[j]);
break;
}
}
}
},
dataType: 'json',
error: function () { console.log("Error retrieving cascading dropdown data from " + actionUrl); }
});
}
else {
$(secondaryDropDown).prop('disabled', true);
}
secondaryDropDown.selectedindex = 0; //this prevents a previous selection from sticking
});
$(primaryDropDown).change();
};
} (jQuery));
You can copy the above jQuery that i created, into <script>...</script> tags in your view, or in a separate script file if you wish (note I updated this to make it cross browser, however the scenario in which i was using is no longer required, it should work however).
In those same script tags, (not in a separate file) you can call the plugin by using the following javascript:
$(document).ready(function () {
var primaryDropDown = document.getElementById('stateId');
var secondaryDropdown = document.getElementById('cityId');
var actionUrl = '#Url.Action("GetData")'
$(primaryDropDown).cascade(secondaryDropdown, actionUrl);
});
Remember to add the $(document).ready part, the page must be fully loaded before you try to make the drop downs cascade.
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
//Dropdownlist Selectedchange event
$("#country").change(function () {
$("#State").empty();
$.ajax({
type: 'POST',
url: '#Url.Action("State")', // we are calling json method
dataType: 'json',
data: { id: $("#country").val() },
// here we are get value of selected country and passing same value
success: function (states) {
// states contains the JSON formatted list
// of states passed from the controller
$.each(states, function (i, state) {
$("#State").append('<option value="' + state.Value + '">' +
state.Text + '</option>');
// here we are adding option for States
});
},
error: function (ex) {
alert('Failed to retrieve states.' + ex);
}
});
return false;
})
});
</script>
<div>
#Html.DropDownList("country", ViewBag.country as List<SelectListItem>, "CountryName", new { style = "width: 200px;" })
</div>
<div>
</div>
<div>
#Html.DropDownList("State", ViewBag.country as List<SelectListItem>)
</div>
From controller I am getting the values
public async Task<ActionResult> Country()
{
Country co = new Country();
List<SelectListItem> li = new List<SelectListItem>();
li.Add(new SelectListItem { Text = "Select", Value = "0" });
li.Add(new SelectListItem { Text = "India", Value = "1" });
li.Add(new SelectListItem { Text = "Nepal", Value = "2" });
li.Add(new SelectListItem { Text = "USA", Value = "3" });
li.Add(new SelectListItem { Text = "Kenya", Value = "4" }); ;
ViewBag.country= li;
return View();
}
public JsonResult state(string id)
{
List<SelectListItem> states = new List<SelectListItem>();
states.Add(new SelectListItem { Text = "--Select State--", Value = "0" });
switch (id)
{
case "1":
states.Add(new SelectListItem { Text = "MP", Value = "1" });
states.Add(new SelectListItem { Text = "UP", Value = "2" });
break;
case "3":
states.Add(new SelectListItem { Text = "USA1", Value = "3" });
states.Add(new SelectListItem { Text = "USA2", Value = "4" });
break;
}
return Json(new SelectList(states, "Value", "Text", JsonRequestBehavior.AllowGet));
}

Resources