I need help filling dependent dropdowns. I have dependent dropdown that work when entering data, select the State dropdown and the dependent dropdowns reload based on the state selected.
Issue is when I want to edit, the state is filled and selected from database, but the dependents don't get filled and selected. The onChange function doesn't get activated or hit.
Here are my codes:
<div class="form-row">
<div class="col">
<div class="form-group">
<label asp-for="Sposted"></label>
<select asp-for="Sposted"
class="form-control"
asp-items="#(new SelectList(#ViewBag.statelist, "Stateid", "Statename" ))"
onchange="sposted(this)">
</select>
</div>
</div>
<div class="col">
<div class="form-group">
<label asp-for="Pcommand"></label>
<select asp-for="Pcommand" class="form-control" id="Pcommand"
asp-items="#(new SelectList(string.Empty, "Commandid", "Cfname"))">
<option>Select ...</option>
</select>
</div>
</div>
<div class="col">
<div class="form-group">
<label asp-for="PayP"></label>
<select asp-for="PayP" id="PayP"
class="form-control"
asp-items="#(new SelectList(string.Empty, "Ppid", "Ppfull"))"></select>
</div>
</div>
</div>
The 2 dropdowns, Pcommand and PayP are dependent on sposted. Again, when editing, the sposted drop down is selected and filled from db, but doesn't cascade to the other 2.
Here is the JS:
<script type="text/javascript">
//$(document).ready(function () {
//$('#Sposted').change(function () {
function sposted(stateid) {
console.log(stateid.value);
var url = '#Url.Content("~/")' + "MemberList/RetPayPoint";
//var ddlsource = "#Sposted";
//$.getJSON(url, { Stateid: $(ddlsource).val() }, function (data) {
$.getJSON(url, { Stateid: stateid.value }, function (data) {
var items = '';
$("#PayP").empty();
$.each(data, function (i, pp) {
items += "<option value='" + pp.value + "'>" + pp.text + "</option>";
});
$('#PayP').html(items);
});
}//});
// });
</script>
Thank you in advance.
A few days later, I have decided to add the controller method that is supposed to fill the dropdowns in the view.
public IActionResult DisplayMem()
{
var statelist = _mr.GetStates().ToList();
statelist.Insert(0, new ToxState { Stateid = 0, Statename = "Select..." });
ViewBag.statelist = statelist;
var rank = _mr.GetRanks().ToList();
rank.Insert(0, new ToxRank { Rankid = 0, Fullname = "Select..." });
ViewBag.rank = rank;
//memid = memlist.FirstOrDefault().MemberId;
var obj = _mr.MemberInfo((long)_ar.FindAcc(long.Parse(HttpContext.Session.GetString("memberid"))).MemId);
return View(obj);
}
All he information needed to fill the view elements are in obj. It loads the selects the state from the id in obj, but the onchange isn't fired to fill the dependent dropdowns.
When editing using selected stateid you need to get both dropdowns data, just like you are getting PayP data by using selected stateid like:
$.getJSON(url, { Stateid: stateid.value }, function (data) {
var items = '';
$("#PayP").empty();
$.each(data, function (i, pp) {
items += "<option value='" + pp.value + "'>" + pp.text + "</option>";
});
$('#PayP').html(items);
});
You will call your function sposted and pass selected stateid both times while creating or editing.
After days of research, I couldn't seem to find a way to to force the onchange to call Ajax to dynamically fill the dependent dropdowns. So I took a cue from Mateen's 3rd comment and rewrote the method in the controller to read load the relevant items into a ViewBag.
public IActionResult DisplayMem()
{
var statelist = _mr.GetStates().ToList();
statelist.Insert(0, new ToxState { Stateid = 0, Statename = "Select..." });
ViewBag.statelist = statelist;
var rank = _mr.GetRanks().ToList();
rank.Insert(0, new ToxRank { Rankid = 0, Fullname = "Select..." });
ViewBag.rank = rank;
var obj = _mr.MemberInfo((long)_ar.FindAcc(long.Parse(HttpContext.Session.GetString("memberid"))).MemId);
ViewBag.payp = _mr.GetPayPoint(obj.Sposted.Value).ToList();
ViewBag.pcommand = _mr.GetCommand(obj.Sposted.Value).ToList();
return View(obj);
}
Related
How can I keep selected values for both dropdown after submit action?
In my scenarios, my cascaded dropdown is populating from partial view. I'm new to ASP.NET Core MVC. Let me know if you want more clarifications.
My view:
<form asp-controller="Recommendation" asp-action="SubmitData" method="post">
<select id="States" class="form-control selectpicker" asp-for="StateID" asp-
items="#(new SelectList(ViewBag.StateList,"StateID","State"))"
placeholder="Select Categories"
onchange="console.log($(this).children(':selected').length)">
</select>
#Html.DropDownListFor(m => m.CityID, new SelectList(""), new {#class="select2
form-control", #style = "width: 100%" })
<button id="btnSubmit" class="btn btn-secondary btn-sm">Submit</button>
</form>
onChange function on first dropdown to call 2nd one:
<script type="text/javascript">
$(document).ready(function () {
$("#States").change(function () {
var StateID = $(this).val();
/*debugger;*/
$("#CityID").empty();
$.ajax({
type: "Get",
url: "/Recommendation/GetCityList?iStateID=" + StateID,
contentType: "html",
success: function (response) {
$("#CityID").append(response);
},
error: function (jqXHR, textStatus, errorThrown) {
}
})
})
});
</script>
Partial View for Child dropdown
<option value="">Select City</option>
#if (ViewBag.CityOptions != null)
{
foreach(var item in ViewBag.CityOptions)
{
<option value="#item.Value">#item.Text</option>
}
}
Controller:
[HttpGet]
public ActionResult IndexGet()
{ // From where I get values.
Entity entity = new Entity();
StateList = gateway.SelectList();
StateList.Insert(0, new Model { StateID = 0, State = "Select State" });
ViewBag.StateList = StateList;
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult SubmitData(RecommendModel recommendModel)
{ // Submit form method and I used RedirectToAction for calling view again.
{
}
return RedirectToAction("IndexGet", "Recommendation");
}
[HttpGet]
public ActionResult GetCityList(long iStateID)
{ // For partial call
Entity entity = new Entity();
MCAlist = entity.GetCityList(iStateID);
ViewBag.CityOptions = new SelectList(MCAlist,"MCAID","MCA");
return PartialView("_CityOptionPartial");
}
Looks like maybe you are using the bootstrap-select plugin. You can try adding $(this).selectpicker('refresh'); at the top of your change event.
On a main page for example the Edit.cshtml I have this code here which renders a select 2 with the country flags and it works fine, but when I attempt to move it into a partial view it does not work.
My Html Field which is inside PleasureCraftEditViewPartial.cshtml
<div class="form-group">
#Html.DisplayNameFor(model => model.MooringCountry)
<select asp-for="MooringCountry" class="form-control select2" style="height:35px" id="MooringCountry" name="MooringCountry">
<option>Please select Mooring Country</option>
</select>
<span asp-validation-for="MooringCountry" class="text-danger"></span>
</div>
The above is in my PleasureCraftEditViewPartial.cshtml
#if (#Model.VesselCat == (int)VesselCat.VesselCatType.Commercial) {
#await Html.PartialAsync("ComercialEditViewPartial")
}
#if (#Model.VesselCat == (int)VesselCat.VesselCatType.MotorBoats ||
#Model.VesselCat == (int)VesselCat.VesselCatType.SailingBoats ||
#Model.VesselCat == (int)VesselCat.VesselCatType.SmallBoats) {
#await Html.PartialAsync("PleasureCraftEditViewPartial")
}
The below is in my Edit.cshtml
<script>
$(function () {
//Initialize Select2 Elements
$('.select2').select2();
var isoCountries = [
{ id: 1, flag: 'gbp', text: 'United Kingdom' },
{ id: 2, flag: 'usa', text: 'United States' }
];
function formatCountry(country) {
if (!country.id) { return country.text; }
var $country = $('<span class="flag-icon flag-icon-' + country.flag + ' flag-icon-squared"></span>' + '<span class="flag-text">' + country.text + "</span>");
return $country;
};
//Assuming you have a select element with name country
// e.g. <select name="name"></select>
$("[id='Flag']").select2({
placeholder: "Please Select a Flag",
templateResult: formatCountry,
data: isoCountries
});
$("[id='MooringCountry']").select2({
placeholder: "Please Select a Mooring Country",
templateResult: formatCountry,
data: isoCountries
});
$('#Flag').trigger('change');
});
</script>
There are no errors in my console
Just an empty dropdown
I am developing an online Hotel Management system in asp[dot]net mvc. I have a list of items and each item has a checkbox in it which is for adding it to the order list whenever it is to be added. Problem is whenever I click "Add To Orders" button I get "error alert". I want Get Method of order controller to be called so that data in it should be shown in the view. Also check whether my post method is right or not?
<div class="form-group">
<div class="col-md-offset-2 col-md-2">
<input value="Add to Orders" class="btn btn-primary" onclick="submitItems()" />
#*<input id="submit" value="Place an Order" class="btn btn- primary" onclick="" />*#
</div>
</div>
<script>
//$('#submit').on('click', function (e) {
// e.preventDefault();
var submitItems = function () {
var arrItems = [];
var commaSepratedValues = "";
$("#itemList input[type=checkbox]").each(function (index, val) {
debugger;
var checkedId = $(val).attr("id");
var arr = checkedId.split("_");
var currentItemId = arr[1];
var isChecked = $("#" + checkedId).is(":checked", true);
if (isChecked) {
arrItems.push(currentItemId);
}
})
if (arrItems.length != 0) {
commaSepratedValues = arrItems.toString();
$.ajax({
url: "/Order/Create",
type: "GET",
data: { ItemList: commaSepratedValues },
success: function (data) {
alert('success');
},
error: function () { alert('error'); }
});
}
}
</script>
Above is the code where my function executes and then the problem arises.
Main Menu
Step 1
Step 2
step 3
in my create [ Http post ] method, all data is inserting except the cascading drop down items. I have Department, Subject and section model. One department can have many subjects, one subject can have many sections. after adding jquery submit portion, it shows, form can not be submitted! then it returns to the index! here is my codes from Section Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Section section)
{
if (ModelState.IsValid)
{
db.Sections.Add(section);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.DepartmentId = new SelectList(db.Departments, "DepartmentId", "Name", section.DepartmentId);
ViewBag.SubjectId = new SelectList(db.Subjects, "SubjectId", "SubjectName", section.SubjectId);
return View(section);
}
Here is my create.chtml under Secion view:
#model MvcBCS.Models.Section
#{
ViewBag.Title = "Create Section";
}
#section scripts {
<script type="text/javascript">
$(function() {
$.getJSON("/Section/Departments/List", function(data) {
var items = "<option> Show Department List </option>";
$.each(data, function(i, department) {
items += "<option value='" + department.Value + "'>" + department.Text + "</option>";
});
$("#Departments").html(items);
});
$("#Departments").change(function() {
$.getJSON("/Section/Subjects/List/" + $("#Departments > option:selected").attr("value"), function(data) {
var items = "<option> Show Subject List </option>";
$.each(data, function(i, subject) {
items += "<option value='" + subject.Value + "'>" + subject.Text + "</option>";
});
$("#Subjects").html(items);
});
});
});
$(function() {
$('#submit').on("click", function () {
var form = $(this).parent("form");
$.ajax({
type: "POST",
url: form.attr('action'),
data: form.serialize()
})
.success(function() {
alert("Your form has been submitted");
})
.error(function() {
alert("Your form has not been submitted");
});
return false;
});
});
</script>
}
<h2>Create Section</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Section</legend>
<label for="Departments">Departments</label>
<select id="Departments" name="Departments"></select>
<label for="Subjects">Subjects</label>
<select id="Subjects" name="Subjects"></select>
<label for="Sections">Section</label>
<input id="Sections" name="Sections" type="text" />
<p>
<input type="submit" id="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
I think you need to change the name/Id of your both dropdownlist regarding your properties in your section.
For Departments to DepartmentId and Subjects to SubjectId. They need to match with so in your Post the binder will attach the correct value
i am using knockout to display items on page. I have a list of groups ex: Group 1, Group 2,... each group is in it's own div. When i click on one of the groups it will open and display the items in the group. Some of my groups don't have any items to display and instead of it not showing anything i would like to change that to display: "No items in group"
I am having trouble doing this in the view in javascript and thought i would be able to do it in my knockout/jquery script
View:
<div class="accordion-group elements-by-item">
<div class="accordion-heading">
<a class="ui_title accordion-toggle text_x-large item_accordion_toggle" data-toggle="collapse" data-parent="#ByTimeIndex"
data-bind="text: Title() != null ? Title() : Identity(), attr: { 'href': '#itemContent_' + Id(), 'data-item-id': Id() }">
</a>
</div>
<div class="accordion-body collapse state-loading" data-bind="attr: { 'id': 'itemContent_' + Id(), 'data-item-id': Id() }">
#Html.Partial("_itemElements")
</div>
</div>
**_itemElements Page:**
<div class="accordion-inner no_border" data-bind="foreach: Children">
<div class="element">
........
</div>
<div>
knockout/Jquery js
$idx.ItemsRetrieved = new Array();
$idx.GetItemContent = function (element) {
var _itemId = element.attr('data-item-id');
var _elementData = $idx.itemData;
this.GetElementContent({
groupId: _itemId,
groupData: _elementData.items,
elementData: _elementData,
apiUrl: _courseIndexOptions.GetitemUrlPrefix + _itemId,
accordionBodySelector: '.accordion-body[data-item-id="' + _itemId + '"]',
accordionBtnSelector: 'a[data-item-id="' + _itemId + '"]',
viewModel: $idx.TimeViewModel
});
}
$idx.GetElementContent = function (options) {
if (linq.From($idx.ItemsRetrieved).Any(function (x) { return x == options.groupId })) {
$(options.accordionBodySelector).removeClass(constants.StateClasses.Loading);
return;
}
return Ajax.Get({
Url: options.apiUrl,
OnSuccess: function (data) {
var _items = linq.From(options.groupData);
var _itemToUpdate = _items.Where(function (x) { return x.Id == options.groupId; });
if (_itemToUpdate.Any()) {
_itemToUpdate.First().Children = data.Items;
}
ko.mapping.fromJS(options.elementData, options.viewModel);
sections.ElementArray.AddRange(data.Items);
$(options.accordionBodySelector).removeClass(constants.StateClasses.Loading);
$idx.ItemsRetrieved.push(options.groupId);
$(options.accordionBtnSelector).click();
}
});
how can i check if the children ItemsRetrieved = 0 and to set a message "No Items" to show in the view page?
You can do that :
<div class="accordion-inner no_border" >
<div data-bind="foreach: Children">
<div class="element">
</div>
</div>
<span data-bind="if : Children().length == 0">No items in group</span>
<div>
I hope it helps.