I am looking for a way to have the "Already" selected and saved value show in the edit form. If user selects to change then it will populate a dropdown. There is a similar question on here like this, however it is not MVC and unfortunately it was not answered and the person who posted it went a different direction all together. I am pretty sure that this can be achieved through javascript/ajax. I am not a javascript/ajax programmer so I am stuck at what to change. The cascading dropdown populates correctly and works fine. Other than the fact that you actually have to select another country first and then change back to original company for the state list to populate. The current JavaScript/ajax populates a dropdown and then stores the "Country, State, City" Ids in the record being saved. This makes it confusing also because I do not want to see the Id in the stored value but the actual name. My code is below.
EDIT This was marked a duplicate, However it really isn't. The Key factor in this Question is "Cascading Dropdown Lists" in which 1 dropdown relies on the one before it to get the information it needs. In the beginning I did not have an issue with this. Now I do! I have implemented what was done in this post Html.DropdownListFor selected value not being set. I now can see the selected items as selected in the dropdowns. That's great, but it broke my cascading effect. It now just populates the whole list in each dropdown. When I try to save it, it will not, I now get an error on save -
System.InvalidOperationException: 'The ViewData item that has the key 'Country' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'.'
So the solutions that are given really only touch on part of the problem I am having. New code is below and I also had to use 'public IEnumerable States { get; set; }' in my view model the proposed 'public SelectList States {get; set;}' did not work as it was looking for an IEnumerable.
EDIT - Changed the 3 Dropdowns. Here are the 3 dropdowns in razor page:
<div class="form-group row">
@Html.LabelFor(model => model.Country, htmlAttributes: new { @class = "control-label col-md-3" })
<div class="col-md-8">
@Html.DropDownListFor(model => Model.Country, Model.Countries, "Select Country", new { @class = "form-control", @id = "ddlCountry" })
@Html.ValidationMessageFor(model => model.Country, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group row">
@Html.LabelFor(model => model.State, htmlAttributes: new { @class = "control-label col-md-3" })
<div class="col-md-8">
@Html.DropDownListFor(model => model.State, Model.States, "Select State", new { @class = "form-control", @id = "ddlState" })
@Html.ValidationMessageFor(model => model.State, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group row">
@Html.LabelFor(model => model.City, htmlAttributes: new { @class = "control-label col-md-3" })
<div class="col-md-8">
@Html.DropDownListFor(model => model.City, Model.Cities, "Select City" , new { @class = "form-control", @id = "ddlCity" })
@Html.ValidationMessageFor(model => model.City, "", new { @class = "text-danger" })
</div>
</div>
This is the JavaScript/Ajax: NOTE: I have tried changing the -
"<option value="' + value.StateId + '">"
To be:
"<option value="' + value.Name + '">"
But does not work as the code relies on the "id" to fetch the next dropdown.
<script type="text/javascript">
$(function () {
$('#ddlCountry').change(function () {
$.ajax({
type: "post",
url: "/Customer/GetStates",
data: { countryId: $('#ddlCountry').val() },
datatype: "json",
traditional: true,
// *can you add the following error callback in your code and update what comes in the console log?*
error: function(_, err) {
console.log(_, err)
},
success: function (data) {
$.each(data, function (index, value) {
$('#ddlState').append('<option value="' + value.StateId + '">' + value.StateName + '</option>');
});
}
});
});
$('#ddlState').change(function () {
$.ajax({
type: "post",
url: "/Customer/GetCities",
data: { stateId: $('#ddlState').val() },
datatype: "json",
traditional: true,
error: function(_, err) {
console.log(_, err)
},
success: function (data) {
$.each(data, function (index, value) {
$('#ddlCity').append('<option value="' + value.CityId + '">' + value.CityName + '</option>');
});
}
});
});
});
EDIT - New Controller Action. Here is my Controller Actions:
public ActionResult UserEditAddress(Guid guid)
{
if (guid == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Addresses addresses = db.Addresses.Find(guid);
if (addresses == null)
{
return HttpNotFound();
}
var model = new EditAddressViewModel();
model.AddressUI = addresses.AddressUI;
model.Line1 = addresses.Line1;
model.Line2 = addresses.Line2;
model.Country = addresses.Country;
model.State = addresses.State;
model.City = addresses.City;
model.ZipCode = addresses.ZipCode;
model.CompanyId = addresses.CompanyId;
model.Countries = new SelectList(db.Countries, "CountryId", "CountryName", addresses.Country);
model.States = new SelectList(db.States, "StateId", "StateName", addresses.State);
model.Cities = new SelectList(db.Cities, "CityId", "CityName", addresses.City);
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UserEditAddress(EditAddressViewModel model)
{
var userId = User.Identity.GetUserId();
if (!ModelState.IsValid)
{
return View(model);
}
Addresses addresses = db.Addresses.Find(model.AddressUI);
addresses.Line1 = model.Line1;
addresses.Line2 = model.Line2;
addresses.Country = model.Country;
addresses.State = model.State;
addresses.City = model.City;
addresses.ZipCode = model.ZipCode;
addresses.CompanyId = model.CompanyId;
db.Entry(addresses).Property(x => x.AddressId).IsModified = false;
db.Entry(addresses).Property(x => x.IsBilling).IsModified = false;
db.Entry(addresses).Property(x => x.IsShipping).IsModified = false;
db.Entry(addresses).Property(x => x.ContactName).IsModified = false;
db.Entry(addresses).Property(x => x.EmailAddress).IsModified = false;
db.Entry(addresses).Property(x => x.PhoneNumber).IsModified = false;
db.Entry(addresses).Property(x => x.FaxNumber).IsModified = false;
//db.Entry(addresses).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index", "Customer", new { UserId = userId });
}
// Get States
public JsonResult GetStates(string countryId)
{
int Id;
Id = Convert.ToInt32(countryId);
var states = from a in db.States where a.CountryId == Id select a;
return Json(states);
}
// Get Cities
public JsonResult GetCities(string stateId)
{
int Id;
Id = Convert.ToInt32(stateId);
var cities = from a in db.Cities where a.StateId == Id select a;
return Json(cities);
}
Your help would be much appreciated as I have spent entirely to long trying to find a resolution for this. Thank you for your help, in advance.