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));
}
Related
I have a view in ASP.NET MVC application, with a dropdownlist and other text fields. The dropdownlist is populated with file names from a specific directory. So, on selection of a specific file name from the dropdownlist, I want to populate other text fields with contents on the selected file. The reading of the file is already taken care of.
I'm struggling with filling in the text fields after file name selection from the dropdownlist.
How can I do this?
<div class="col-lg-4">
#Html.DropDownList("cardProgram", null, "--Select--", new { #class = "form-control input-group-lg" })
</div>
Ajax code:
$(document).ready(function () {
$("#FileDDL_ID").change(function () {
var file = $('#FileDDL_ID option:selected').text();
$.ajax({
url: "#Url.Action("YourAction", "Controller")",
type: "POST",
dataType: "json",
data: { filename: file }, //pass file as parameter to controller
async: false,
error: function () {
},
//assuming your data property is called fileDetail1
success: function (data) {
if (Object.keys(data).length > 0) {
$('#fileDetailtxtBox1').val(data[0].fileDetail1);
$('#fileDetailtxtBox2').val(data[0].fileDetail2);
}
}
});
});
});
Controller code:
[HttpPost]
public JsonResult YourAction(string filename)
{
using (var db = new DataContext())
{
//use filename as condition
var details = db.YourDbset.Condition.ToList();
return Json(details, JsonRequestBehavior.AllowGet);
}
}
Hope this is clear, I have tried to name variables as per your question. So basically, you are passing the selected value from the dropdown to the Controller action and getting back related data and populating fields with jQuery Ajax.
I finally got it working. See below :
html code:
#Html.LabelFor(m => m.cardProgram, new { #class = "col-lg-2" })
<div class="col-lg-4">
#Html.DropDownListFor(m => m.cardProgram, null, "--Select Card Profile--", new
{
#class = "col-lg-4 form-control input-group-lg",
#onchange = "BindProfile()"
})
</div>
ajax code:
<script>
function BindProfile() {
var selectedProfile = $('#cardProgram').val();
$.ajax({
url: '/CardCreation/BindProfile',
type: "GET",
dataType: "JSON",
data: { cardProgram: selectedProfile },
success: function (profile) {
$("#sBin").val(profile.card.bin)
$("#IsChip").val(profile.card.chip)
$("#IsBatches").val(profile.output.splitBatches)
$("#BatchSize").val(profile.output.batchSize)
$("#SplitPostcard").val(profile.output.splitPostcardFile)
$("#SubCat").val(profile.batchDetails.subcategory)
$("#UserCodeIncrement").val(profile.batchDetails.usercodeIncrement)
$("#ExpiryDate").val(profile.batchDetails.expiryWindowMM)
$("#Bureau").val(profile.chipDetails.bureau)
$("#BatchType").val(profile.chipDetails.batchType)
$("#EffectiveDate").val(profile.chipDetails.effectiveDateOffsetMM)
$("#ServiceCode").val(profile.emvApplications[0].serviceRestrictionCode)
}
});
}
</script>
Controller code:
public async Task<ActionResult> BindProfile(string cardProgram)
{
var profile = new Profile();
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:59066/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
ViewBag.country = "";
HttpResponseMessage response = await client.GetAsync(client.BaseAddress + "api/CardCreation/GetSelectedCardProfile?selectedProfile=" + cardProgram);
if (response.IsSuccessStatusCode)
{
//profile = response.Content.ReadAsAsync<Profile>().Result;
profile = JsonConvert.DeserializeObject<Profile>(response.Content.ReadAsStringAsync().Result);
return Json(profile, JsonRequestBehavior.AllowGet);
}
else
{
return Json(profile, JsonRequestBehavior.AllowGet); ;
}
}
}
I've coded for multiple values that resides inside listbox on button click. I have used autocomplete textbox to get the required value along with its id. Then i managed to add those values inside the listbox. Now what i want is to pass id's against those values in listbox instead of names. Below is my code that I'm running.
StudentBatch.cs
public string studentId { get; set; }
public string StudentName { get; set; }
public List<string> selectedids { get; set; }
public List<string> names { get; set; }
public List<string> SelectedNames { get; set; }
Create.cshtml
#using (Html.BeginForm("Create", "Student", FormMethod.Post))
{
<div class="form-group">
<div class="col-md-12">
#Html.EditorFor(model => model.StudentName, new { id = "StudentName" })
<input type="button" value="Add Text" id="addtypevalue" />
<div id="typevaluelist"></div>
</div>
</div>
<div id="new" style="display:none;">
<div class="typevalue">
<input type="text" name="typevalue" />
<button type="button" class="delete">Delete</button>
</div>
</div>
<div id="hiddensq">
</div>
for (int i = 0; i < Model.names.Count; i++)
{
#Html.Hidden("UserValues", Model.names[i]);
}
#Html.ListBoxFor(m => m.SelectedNames, new SelectList(Model.names))
<div id="partialDiv">
#{
Html.RenderPartial("GetListBox", Model);
}
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
}
<script type="text/javascript">
$(document).ready(function () {
$("#StudentName").autocomplete({
//autocomplete: {
// delay: 0,
// minLength: 1,
source: function (request, response)
{
$.ajax({
url: "/Student/CreateStudent",
type: "POST",
dataType: "json",
data: { Prefix: request.term },
success: function(data) {
try {
response($.map(data,
function (item)
{
return { label: item.FirstName, id: item.Id };
}));
} catch (err) {
}
}
});
},
messages:
{
noResults: "jhh", results: "jhjh"
}
});
});
</script>
<script>
$(function () {
$('#addtypevalue').click(function (e) {
var name = $("#StudentName").val();
alert(name);
$('#SelectedNames').
append($("<option></option>").
attr("value", name).
text(name));
$('#hiddensq').append("<input name='UserValues' type='hidden' value='"+ name +"'/>");
});
});
</script>
StudentController.cs
public ActionResult Create()
{
Context.Student student = new Context.Student();
Models.StudentBatch studBatch = new Models.StudentBatch();
studBatch.names = new List<string>();
studBatch.names.Add("Add Student Names");
studBatch.BatchNumberList = student.getBatchList();
return View(studBatch);
}
[HttpPost]
public JsonResult CreateStudent(string Prefix)
{
CreateUser user = new CreateUser();
string stdid = "f14570f0-e7a1-4c22-bf69-60ffbeb7e432";
var StudentList1 = user.GetAllUsers().ToList().Where(u => u.FirstName.Contains(Prefix) && u.usertypeid == stdid);
var StudentList = user.GetAllUsers().ToList();
var searchlist = (from student in StudentList1
where student.FirstName.Contains(Prefix)
select student).ToList();
return Json(StudentList1, JsonRequestBehavior.AllowGet);
}
// POST: Student/Create
[HttpPost]
public ActionResult Create(Models.StudentBatch student, IEnumerable<string> UserValues)
{
try
{
// TODO: Add insert logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
If I understood correctly the problem here is passing multiple IDs from a listbox to a POST? One possible way is to assign viewbag like thus in your controller:
ViewBag.StudentList = new SelectList(db.StudentBatch, "studentId", "StudentName");
I use entities to access my models, I think you have a little bit different approach but the point is to give a collection to the Selectlist. Then you specify the data value field and the data text field.
Then in your view, note that it's not ListBoxFor, as it's dynamic:
#Html.ListBox("StudentList", null)
Then finally to be able to receive the values in the POST add the following parameter to your action and you should be able to iterate through it:
string[] StudentList
Finally managed to get the related from the listbox. I followed the instruction mentioned in a particular question. That's how i did.
$("#StudentName").autocomplete({
source: function (request, response) {
$.ajax({
cache: false,
// async: false, NEVER do this
url: '#Url.Action("CreateStudent", "Student")', // don't hard code your url's
data: { Prefix: request.term }, // change
dataType: "json",
type: "POST",
// contentType: "application/json; charset=utf-8", delete
success: function (data) {
response($.map(data, function (item) {
return {
label: item.label,
id: item.id
}
}));
}
})
},select: function(event, ui) {
$.ajax({
cache: false,
type: "POST",
url: '#Url.Action("GetDetails", "Student")',
data: { id: ui.item.id },
success: function (data) {
var name = $("#StudentName").val();
$('#SelectedNames').
append($("<option></option>").
attr("value", ui.item.id).
text(name));
$('#hiddensq').append("<input name='UserValues' type='hidden' value='" + ui.item.id + "'/>");
}
});
}
});
</script>
and in the controller class
[HttpPost]
public JsonResult GetDetails(string id)
{
ViewBag.Value = id;
return Json(ViewBag.Value, JsonRequestBehavior.AllowGet);
}
I started using web grid from last couple of days. Everything was so handy with webgrid like displaying columns with different datatype like textbox, label, drop down etc. But how do I save data or update data.
I tried using action link and submit buttons but none of them worked for me. They weren't fetching the modified drop down data in my controller. The action link was able to fetch the user id but it couldn't get the changed drop down value.
Below is the code:
View
WebGridColumn colLocation = null;
foreach (var col in Model)
{
colLocation = new WebGridColumn()
{
Header = "Locations",
Format = (item) => #Html.DropDownList("LocationId", #col.LocationItems.Select(l => new SelectListItem
{
Text = l.Text,
Value = l.Value,
Selected = ((WebGridRow)item)["LocationId"].ToString() == l.Value
}
)
)
};
colSave = new WebGridColumn()
{
Header = "Save User",
Format = (item) => Html.ActionLink("Save", "Save", "UsersList", new { userId = item.UserId, locationId = item.LocationId }, new { #class = "btn btn-default" }),
CanSort = true
};
}
columns.Add(colLocation);
columns.Add(colSave);
#grid.GetHtml(tableStyle: "webgrid",
headerStyle: "header",
selectedRowStyle: "select",
alternatingRowStyle: "alt",
columns: columns
)
Controller
public ActionResult Save(int userId, int locationId)
{
var user = Utility.SetUserDetails(userId, locationId);
return RedirectToAction("UsersList");
}
After some rigorous trials, I've achieved this functionality. This can be done using ajax.
I've to extend my column properties to include class & id attribute
colUser = new WebGridColumn()
{
Header = "User Id",
ColumnName = "UserId",
CanSort = true,
Format = #<text>
<span class="display"><label id="lblUserId">#item.UserId</label></span>
<input type="text" id="inUserId" value="#item.UserId" class="edit" style="visibility:hidden" />
</text>
};
colLocation = new WebGridColumn()
{
Header = "Locations",
Format = #<text>
#Html.DropDownList("Location", #col.LocationItems.Select(l => new SelectListItem
{
Text = l.Text,
Value = l.Value,
Selected = ((WebGridRow)item)["LocationId"].ToString() == l.Value
}
), new { #class = "edit", #id = "inLocation" })
</text>
};
colSave = new WebGridColumn()
{
Header = "Save User",
Format = #<text>
Save
</text>
};
After adding the jquery script, we can post the selected values into controller,
<script type="text/javascript">
$(function () {
$('.save-btn').on("click", function () {
var tr = $(this).parents('tr:first');
var id = tr.find("#inUserId").val();
var location = tr.find("#inLocation").val();
var User =
{
"UserId": id,
"LocationId": location
};
$.ajax({
url: '/UsersList/SaveData/',
data: JSON.stringify(User),
type: 'POST',
contentType: 'application/json; charset=utf-8',
success: function (result) {
isSuccess = result;
},
error: function (result) {
isSuccess = result;
}
})
});
});
</script>
In the controller, add new method,
public ActionResult SaveData(UserAccountViewModel User)
{
int userId = User.UserId;
int locationId = Convert.ToInt32(User.LocationId);
var user = Utility.SetUserDetails(userId, locationId);
return RedirectToAction("UsersList");
}
I have Three CaseCade Comboboxes, which work just fine for me
The problem is begins when I want to SAVE the id that Are Selected ,
I know how to get the Selected Id Which will be like this, and i have no problem with that
var countries = $("#countries").data("kendoDropDownList")
countries.value()
i don't know how to Set this values in my view model that i defined Above in My view, i don't know a way to pass view model to POST function.
This Is My View
#using System.Web.Optimization
#using Kendo.Mvc.UI
#model Mfr.Admin.Models.Address.CreateViewModel
#{
Layout = "~/Views/Shared/_Main.cshtml";
}
<
<div class="demo-section k-content">
<h4>Countries:</h4>
#(Html.Kendo().DropDownListFor(m=>m.CountryId)
.HtmlAttributes(new {style = "width:100%"})
.OptionLabel("Select Country...")
.DataTextField("Title")
.DataValueField("Id")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetCascadeCountries", "Address");
});
})
)
<h4 style="margin-top: 2em;">states:</h4>
#(Html.Kendo().DropDownListFor(m=>m.StateId)
.HtmlAttributes(new {style = "width:100%"})
.OptionLabel("Select state...")
.DataTextField("stateTitle")
.DataValueField("stateId")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetCascadeStates", "Address")
.Data("filterStates");
})
.ServerFiltering(true);
})
.Enable(false)
.AutoBind(false)
.CascadeFrom("CountryId")
)
<script>
function filterStates() {
return {
countries: $("#CountryId").val()
};
}
</script>
<h4 style="margin-top: 2em;">cities:</h4>
#(Html.Kendo().DropDownListFor(m=>m.CityId)
.HtmlAttributes(new {style = "width:100%"})
.OptionLabel("Select city...")
.DataTextField("cityTitle")
.DataValueField("cityId")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetCascadeCities", "Address")
.Data("filterCities");
})
.ServerFiltering(true);
})
.Enable(false)
.AutoBind(false)
.CascadeFrom("StateId")
)
<script>
function filterCities() {
return {
cities: $("#StateId").val()
};
}
</script>
<button class="k-button k-primary" id="get" style="margin-top: 2em; float: right;">Save</button>
</div>
<script>
$(document).ready(function () {
$("#get").click(function () {
// I want To call My post function Here, and pass viewmodel with initialized values to that
// I Suppose It will be something like this
//but I dont know how to set values to view model
//$.ajax({
// url: "#Html.Raw(Url.Action("Create", "Address"))",
// type: "POST",
// dataType: "json"
//)};
});
});
</script>
<style>
.k-readonly {
color: gray;
}
This is My save Action
address here is not initialized
[HttpPost]
public ActionResult Create(CreateViewModel address)
{
if (address == null)
throw new ArgumentNullException(nameof(address));
var addressModel = new Address()
{
Description = address.Description,
CityId = address.CityId,
StateId = address.StateId,
CountryId = address.CountryId,
UserApplicationId = User.Identity.GetUserId<int>()
};
_addressRepository.Add(addressModel);
_addressRepository.Complete();
return Json("");
}
this is view model
public class CreateViewModel
{
public int Id { get; set; }
public int UserApplicationId { get; set; }
public int CountryId { get; set; }
public int StateId { get; set; }
public int CityId { get; set; }
public string Description { get; set; }
}
You just need to send json back to controller
var countries = $("#countries").data("kendoDropDownList")
var countryId = countries.value();
var id = ..... //and so on
var data = {'Id': id, 'CountryId': countryId, /*ad so on*/ }
...
data: JSON.stringify(data)
...
Collect all data you need, put it in json object, stringify and if json properties correspond correctly to model properties, it will be automatically binded to controllers parameter.
my jquery is like this
<script type="text/javascript">$(document).ready(function(){
$("#drpId").change(function(e) {
firstDDLValue = $("#drpId").val();
$.post('#Url.Action("GetDataForSecond", "Login")', { fstValue: firstDDLValue }, function (e) {
var select = $("#secondDDLID");
select.empty();
$.each(result, function (index, Data) {
select.append($('<option/>', {
value: result.Value,
}));
});
});
});
});
My controller code is
public JsonResult GetDataForSecond(string fstValue)
{
Domain obj = new Domain();
var data = obj.LoadSubDomain(fstValue); return Json(data, JsonRequestBehavior.AllowGet);
in data i am getting all the values of second dropdown but in view its not binding.
and my view code is just like this
<div class="editor-field">
#{
var data = ViewBag.MyData;
<select name="drpId" id="drpId">
<option value="yourvalue">Select DomainName </option>
#foreach (var te in data)
{
<option>#te.DomainName</option>
}
</select>
}
#Html.ValidationMessageFor(model => model.DomainName)
</div>
<div class="editor-field">
<select name="secondDDLID" id="secondDDLID">
<option value="yourvalue"></option>
</select>
</div>
Do this:
In your view add this script:
$("#drpId").change(function () {
firstDDLValue = $("#drpId").val();
$.post('#Url.Action("GetDataForSecond", "Login")', { fstValue: firstDDLValue }, function (result) {
var select = $("#secondDDLID");
select.empty();
$.each(result, function (index, Data) {
select.append($('<option/>', {
value: Data.Value,
text: Data.Text
}));
});
});
});
And method to bind second ddl in controller:
public JsonResult GetDataForSecond(string fstValue)
{
Domain obj = new Domain();
var result = obj.LoadSubDomain(fstValue);
IList < SelectListItem > Data = new List<SelectListItem>();
for (int i = 0; i < result.Count; i++)
{
Data.Add(new SelectListItem()
{
Text = result[i].Name,
Value = result[i].Name,
});
}
return Json(Data, JsonRequestBehavior.AllowGet);
}