I want to know if there is any possibility of me posting Text value from a nested Dropdown in MVC??
I have been able to populate the dropdown with my database values and it is cascaded that when the first dropdown it picked, It automatically populate the second dropdown with a json result. I want to post the text value from the dropdown, it is posible??
This is my controller with the JSON call
[HttpPost]
public ActionResult Index(SchoolRegViewModel model, HttpPostedFileBase Logo)
{
var queryCountry = _countryState.GetAllCountry().Select(s => new SelectListItem
{
Value = s.CountryId.ToString(),
Text = s.CountryName,
Selected = false
});
model.Country = queryCountry.AsEnumerable();
var country = model.Country.Select(x => x.Text).Single();
if (ModelState.IsValid)
{
try
{
....
}
catch (Exception ex)
{
throw ex;
}
}
return View(model);
}
public JsonResult StateList(int? id)
{
if (id != null)
{
var state = _countryState.GetAllState(id.Value);
return Json(new SelectList(state, "CountryId", "StateName"), JsonRequestBehavior.AllowGet);
}
else
{
return Json(new { }, JsonRequestBehavior.AllowGet);
}
}
this is my jquery that populate the second dropdown with json result
jQuery(function ($) {
$(function ()
{
$('#CountryId').change(function () {
$.getJSON('/Registration/Registration/StateList/' + $('#CountryId').val(), function (data) {
var items = '<option>-- Select State --</option>';
$.each(data, function (i, state) {
items += "<option value = '" + state.Value + "'>" + state.Text + "</option>";
});
$('#State').html(items);
$('#State option:selected').text();
});
});
});
});
View
<div class="control-group">
<label for="text" class="control-label">Country</label>
<div class="controls">
#Html.DropDownListFor(model => model.CountryId, Model.Country, "-- Choose Country --", new { id = "CountryId", required="true"})
</div>
</div>
<div class="control-group">
<label for="text" class="control-label">State/Provinces</label>
<div class="controls">
<select name="State" id="State" data-rule-required="true">
</select>
</div>
</div>
Just make the value parameter the same as what you're putting in for the text.
new SelectList(state, "StateName", "StateName")
And:
items += "<option value = '" + state.Text + "'>" + state.Text + "</option>";
Related
I am trying to build a cascading dropdown list with a list of countries mapped with their corresponding states. The data is being accessed from SQL Server. I am able to build the country list using the db. However, I am unable to see the data for the states.
CountryStateService.cs:
public async Task<IEnumerable<StateModel>> GetStates(int countryId) {
var data = await (from cs in db.CountryStates
where cs.IdCid == countryId
select new StateModel
{
stateId = cs.stateId,
stateName = cs.stateName,
IdCid = cs.IdCid
}).ToListAsync();
return data;
}
Home Controller:
[HttpGet]
public async Task<IActionResult> LoadStateForCountry(int countryId) {
var stateCollection = await _service.GetStates(countryId);
List<StateModel> stateList = stateCollection.ToList();
ViewBag.StateList = stateList;
return View();
}
JQuery: [This is likely the problem as I am unable to see the data.]
<script type="text/javascript">
$(document).ready(function() {
$('#countryDropDown').change(function() {
// show the state dropdown only if a country is selected
if ($('#countryDropDown option:selected').text != '') {
$('#stateDropDown').prop('disabled', false);
var selectedCountry = $(this).val();
var options = `<option value=0> Select State </option>`
$('#stateDropDown').empty();
// get the location of the selected country
$.getJSON("/Home/LoadStateForCountry/?countryId=" + selectedCountry, function(data) {
$.each(data, function(i, stateDetails) {
options += "<option value=" + this['stateId'] + ">" + this['stateName'] + "</option>"
});
$("#stateDropDown").html(options)
})
} else {
$('#stateDropDown').prop('disabled', true);
}
});
});
Razor Page
<select class="form-control form-control-md my-2"
id="stateDropDown"
placeholder="Select State"
asp-items="#ViewBag.StateList">
</select>
Since you want to get data from LoadStateForCountry,you should return stateList in the action:
[HttpGet]
public async Task<IActionResult> LoadStateForCountry(int countryId) {
var stateCollection = await _service.GetStates(countryId);
List<StateModel> stateList = stateCollection.ToList();
//ViewBag.StateList = stateList;
return new JsonResult(stateList);
}
In dropdown am fetching the value from the database i't is working fine ..i need to add <option value='-1'>Root</option> by manually which is not present in the database.
<div class="col-lg-4">
<fieldset class="form-group">
<label class="form-label" for="exampleInput">Domain Name</label>
#Html.DropDownList("DomainID", null, "--- Select Domain Name ---", new { #class = "select2-arrow" })
#Html.ValidationMessageFor(model => Model.DomainID, null, new { #style = "color: red" })
</fieldset>
</div>
<div class="col-lg-4">
<fieldset class="form-group">
<label class="form-label" for="exampleInput">Parent Module</label>
<select id="ParentModuleID" class="select2-arrow" name="ParentModuleID"></select>
#Html.ValidationMessageFor(model => Model.ParentModuleID, null, new { #style = "color: red" })
</fieldset>
</div>
Jquery:
$("#DomainID").change(function () {
var id = $(this).val();
$("#ParentModuleID").empty();
$.get("ParentModule_Bind", { DomainID: id }, function (data) {
var v = "<option>--- Select Domain Name ---</option>";
$.each(data, function (i, v1) {
v += "<option value=" + v1.Value + ">" + v1.Text + "</option>";
});
$("#ParentModuleID").html(v);
});
});
in above jquery <option>--- Select Domain Name ---</option> i need to add root with value of -1
public JsonResult ParentModule_Bind(string DomainID)
{
userType type = new userType();
DataSet ds = type.ParentModule_Bind(DomainID);
List<SelectListItem> statelist = new List<SelectListItem>();
foreach (DataRow dr in ds.Tables[0].Rows)
{
statelist.Add(new SelectListItem { Text = dr["ModuleName"].ToString(), Value = dr["ModuleID"].ToString() });
}
return Json(statelist, JsonRequestBehavior.AllowGet);
}
You can either add a line in jQuesry like this
v += "<option value='-1'>root</option>";
or add a line in controller above foreach like this
statelist.Add(new SelectListItem { Text = "root", Value = "-1" });
to achieve the result.
Why do any of this in the UI with jQuery?
One big problem I see is that your are mixing business logic of your list data with UI manipulation.
If this value is always needed for the ParentModel list regardless of DomainID, then I'd modify you method that returns you the list
public JsonResult ParentModule_Bind(string DomainID)
{
userType type = new userType();
DataSet ds = type.ParentModule_Bind(DomainID);
//change the following line
var statelist = new List<SelectListItem> { new SelectListItem { Text = "Root", Value = "-1" };
foreach (DataRow dr in ds.Tables[0].Rows)
{
statelist.Add(new SelectListItem { Text = dr["ModuleName"].ToString(), Value = dr["ModuleID"].ToString() });
}
return Json(statelist, JsonRequestBehavior.AllowGet);
}
I am doing an mvc 5 project and I have cart view and I have 2 deopdownlist named country and state in it and when it is run the country model fill country dropdownlist and now I want to fill state dropdownlist onchange of country dropdownlist so I used code below to do this but it does not work successfully.i debug this code it works correctly the only problem is that this code can not append to state dropdownlist.I dont know what to do
#model IEnumerable<NewMVCWebApp.Models.Country>
<script>
function f11() {
var a = $("#se option:selected").text();
var b = $("#se option:selected").index();
$.ajax({
url: "/State/GetStates",
data: { a: a, b: b },
type:"post",
success: function (value) {
cities = JSON.parse(value);
$("#ss").html("");
$("#ss").append("<option>--- please select---</option>");
$.each(cities, function (idx, city) {
$("#ss").append("<option value='" + city.ID + "'>" + city.name + "</option>")
})
},
error: function () {
$("#lbl").html("Error in Ajax...!");
}
})
}
</script>
<div class="tabs-b">
<ul>
<li>estimate</li>
</ul>
<div>
<div>
<p>enter destination</p>
<p class="required">
<label for="sha">Country</label>
<select id="se" name="Country" onchange="f11()">
<option>--- please select ---</option>
#foreach (var item in Model)
{
<option value="#item.ID">#item.name</option>
}
</select>
</p>
<p class="required">
<label>region</label>
<select id="ss"></select>
</p>
<p>
<label for="shc">post code</label>
<input type="text" name="shc" id="shc" required="">
</p>
<p class="link-c">#*get*#</p>
</div>
<div>
<p></p>
</div>
<div>
<p></p>
</div>
</div>
</div>
the action in the controller
public string GetStates(string a,string b)
{
JavaScriptSerializer js = new JavaScriptSerializer();
List<state> states = _context.states.Where(x => x.IDK == Idk).ToList();
return js.Serialize(states.Select(x => new { ID = x.ID, name = x.name }));
}
In controller change method type to JsonResult
public JsonResult GetStates(int index)
{
JsonResult json = new JsonResult();
json.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
json.Data = _context.states.Where(x => x.IDK == index).ToList();
return json;
}
and in html file
function f11() {
var index = $("#se option:selected").val();
$.ajax({
url: "/State/GetStates",
data: { index: index },
type:"post",
success: function (value) {
var result = "";
$("#ss").append("<option>--- please select---</option>");
$.each(value, function (index, city) {
result += "<option value='" + city.ID + "'>" + city.name + "</option>";
});
$("#ss").append(result);
},
error: function () {
$("#lbl").html("Error in Ajax...!");
}
})
}
I have controls that insert from jQuery. The controls can change depending on the option you choose before, that is, they are not controls have created statically, but to think through jQuery with the option you choose.
My question is is possible to access a list of controller in HttpPost?
This is the function that performed to insert controls:
function GetProperties() {
var subcategory = $("#ddlSubcategory").val();
$.getJSON("/AddAdBox/GetProperties?id=" + subcategory, null, function (data) {
$.each(data, function (i, item) {
//item.ID // PROPERTY ID
//item.NAME //NAME PROPERTY
//item.OPTION_PROPERTY[0].ID //ID OPTION ID
//item.OPTION_PROPERTY[0].NAME // NAME OPTION
//item.OPTION_PROPERTY.length // SI ES 0 ES TXT SINO SELECT
var itemlist = '';
//<div class="col-sm-6">
// <label>
// Título
// </label>
// <input type="text" name="email" class="form-control" placeholder="Título">
// </div><!-- /.col -->
if (item.OPTION_PROPERTY != null) {
if (item.OPTION_PROPERTY.length > 0) {
itemlist = '<div class="col-sm-6 animated" style="opacity:1;"><label>' + item.NAME + '</label>';
itemlist += '<select id="ddl"' + item.NAME + '">';
for (var i = 0; i < item.OPTION_PROPERTY.length; i++) {
itemlist += '<option value="' + item.OPTION_PROPERTY[i].ID + '">' + item.OPTION_PROPERTY[i].NAME + '</option>';
}
itemlist += '</selec>';
itemlist += '</div>';
}
}
else {
itemlist = '<div class="col-sm-6 animated" style="opacity:1;"><label>' + item.NAME + '</label>';
itemlist += '<input type="text" name="' + item.NAME + '" class="form-control" placeholder="' + item.NAME + '">';
itemlist += '</div>';
}
$("#properties").append(itemlist);
});
});
}
One way to bind data to a controller, from dynamic HTML elements, is by using a custom model binder. For example:
In my controller I use a viewmodel:
public class IndexViewModel
{
public int SelectedItemId { get; set; }
}
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new IndexViewModel());
}
[HttpPost]
public ActionResult Index(IndexViewModel viewModel)
{
return View(viewModel);
}
}
I then create a custom model binder that can work with that viewmodel:
public class IndexViewModelBinder : DefaultModelBinder
{
protected override void OnModelUpdated(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
string[] allKeys = HttpContext.Current.Request.Form.AllKeys;
var viewModel = bindingContext.Model as IndexViewModel;
viewModel.SelectedItemId = int.Parse(HttpContext.Current.Request.Form[0]);
}
}
In your Global.asax.cs file, place this in the Application_Start()
ModelBinders.Binders.Add(typeof(IndexViewModel), new IndexViewModelBinder());
In my view file I have:
#model SelectListModelBinding.Controllers.IndexViewModel
#{
ViewBag.Title = "Home Page";
}
#using (Html.BeginForm())
{
<div class="col-sm-6 animated" style="opacity:1;">
<label>FooName</label>';
<select name="ddlFooName" id="ddlFooName">
<option value="1">Item 1</option>
<option value="2">Item 2</option>
</select>
</div>
<input type="submit" value="Save" />
}
You can pretend that the <select> was dynamically generated. Now when I post back to the controller, the IndexViewModelBinder is executed and I can see the values passed in the Form property of the current request. I can then pick out whatever data I need. In my example I'm picking out the id of the selected list item from ddlFooName
Since the names of the dropdowns will be dynamic, you may have to do some stuff with the Form.AllKeys to pick out stuff that starts with "ddl" and use that key to get the data.
I am attempting to do some duplication checking in my MVC5/EF Code-First application. On my Create() Asset View, I show/hide textboxes for entering a new location_dept/location_room via JS:
<div class="form-group">
#*#Html.LabelFor(model => model.Location_Id, "Location_Id", htmlAttributes: new { #class = "control-label col-md-2" })*#
<span class="control-label col-md-2">Location:</span>
<div class="col-md-4">
#*#Html.DropDownList("Location_Id", null, htmlAttributes: new { #class = "form-control dropdown" })*#
#Html.DropDownListFor(model => model.Location_Id, (SelectList)ViewBag.Model_List, htmlAttributes: new { #class = "form-control dropdown", #id = "selectLocation" })
#Html.ValidationMessageFor(model => model.Location_Id, "", new { #class = "text-danger" })
</div>
<div class="col-md-2">
<div class="btn-group">
<button id="createNewLocation" type="button" class="btn btn-success" aria-expanded="false">CREATE NEW</button>
</div>
</div>
<div class="col-md-4">
<div id="createLocationFormContainer" style="display:none">
<form action="/createNewLocation">
<input type="text" id="textNewLocationDept" name="location_dept" placeholder="New Department" />
<input type="button" id="submitNewLocation" value="Submit" />
<input type="button" id="cancelNewLocation" value="Cancel" /><br />
<input type="text" id="textNewLocationRoom" name="location_room" placeholder="New Room" />
</form>
</div>
</div>
</div>
JS:
$('#createNewLocation').click(function () {
$('#createLocationFormContainer').show();
})
$('#cancelNewLocation').click(function () {
$('#createLocationFormContainer').hide();
})
$('#submitNewLocation').click(function () {
var form = $(this).closest('form');
var data = { location_dept: document.getElementById('textNewLocationDept').value, location_room: document.getElementById('textNewLocationRoom').value };
// CORRECTLY SHOWING
alert("Dept: " + data.location_dept + " | Room: " + data.location_room);
$.ajax({
type: "POST",
dataType: "JSON",
url: '#Url.Action("createNewLocation", "INV_Assets")',
data: data,
success: function (resp) {
if (resp.LocationRoomExists)
{
alert("Room Location [" + resp.Text + "] already exists. Please select from the DropDown.");
} else {
// FALSE
alert("LocationRoomExists: " + resp.LocationRoomExists);
// `undefined` returned for both values
alert("Department: " + resp.location_dept + " | Room: " + resp.location_room);
$ $('#selectLocation').append($('<option></option>').val(resp.ID).text(resp.LocDept + "| " + resp.LocRoom));
$('#createLocationFormContainer').hide();
var count = $('#selectLocation option').size();
$("#selectLocation").prop('selectedIndex', count - 1);
}
},
error: function () {
alert("ERROR - Something went wrong adding new Room Location [" + resp.Text + "]!");
$('#createLocationFormContainer').hide();
}
});
});
I then use a JSON POST to my controller action to create the new INV_Location:
[HttpPost]
public JsonResult createNewLocation(string department, string room)
{
INV_Locations location = new INV_Locations()
{
// ID auto-set during save.
location_dept = department,
location_room = room,
created_date = DateTime.Now,
created_by = System.Environment.UserName
};
var duplicateLocation = db.INV_Locations.FirstOrDefault(x => x.location_room.ToUpper() == location.location_room.ToUpper());
try
{
if (duplicateLocation == null)
{
if (ModelState.IsValid)
{
db.INV_Locations.Add(location);
db.SaveChanges();
}
}
else
{
location = duplicateLocation;
}
}
catch (Exception ex)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
}
return Json(new { ID = location.Id, LocDept = location.location_dept, LocRoom = location.location_room, LocationRoomExists = (duplicateLocation != null) }, JsonRequestBehavior.AllowGet);
}
When I run the code all together, I get a result in my dropdown of undefined|undefined. After some debugging I determined that my controller is not receiving a department/room value (null).
Can anyone spot what might be going wrong with my AJAX call to my controller?
EDIT:
$('#selectLocation').append($('<option></option>').val(resp.ID).text(resp.LocDept + "| " + resp.LocRoom));
You need to make sure your parameters match that you are sending:
var data = { department: document.getElementById('textNewLocationDept').value, room: document.getElementById('textNewLocationRoom').value };
You also need to match the data that you are returning from your controller.
Your action returns this:
new { ID = location.Id, LocDept = location.location_dept,
LocRoom = location.location_room,
LocationRoomExists = (duplicateLocation != null) }
So your bind needs to match the properties i.e.
$('#selectLocation').append($('<option></option>')
.val(resp.Id).text(resp.LocRoom + "| " + resp.LocDept ));