I am new and struggling to find a way to create a searchable dropdownlist (MVC5/C#). I have tried Select2, and could not get it working. I am desperate and out of time.
Looking at a few tutorials on Jquery Autocomplete, it seems pretty straight and forward. My problem is that all of the examples on line seems to use static data. My dropdownlist is populated from my Controller using a List of pre-filtered results.
This is how I populate my doprdownlist
List<SelectListItem> autocomplete = db.ICS_Supplies.Where(s => s.InvType == "F").Select(x => new SelectListItem { Value = x.Supplies_ID.ToString(), Text = x.Old_ItemID + " " + " | " + " " + " Description: " + x.ItemDescription, Selected = false }).DistinctBy(p => p.Text).OrderBy(p => p.Text).ToList();
ViewBag.FormsList = new SelectList(autocomplete, "Value", "Text");
As is, the dropdown populates - but it has a lot of records and is VERY slow.
From most of the examples I have seen online, the searchable items are something like:
var options = [
{ value: 'Adam', data: 'AD' },
// ...
{ value: 'Tim', data: 'TM' }
];
That's great, if I want to type out a thousand possible items - but I need to populate my DropDownList options from a table. .. and I am lost.
I am very new to Jquery and any direction is greatly appreciated.
EDIT1*
I am adding the View Code (from the online Example) for more clarification
<div class="form-group col-sm-5">
<label for="files">Select Supply:</label>
<input type="text" name="supplies" id="autocomplete" />
</div>
<div>
Selected Option : <span class="label label-default" id="selected_option"></span>
</div>
I suggest you need ajax to get a dynamic autocomplete list. Here's some sample code - it's the definition of a basic jQuery implementation that uses ajax.
function close_autocomplete($elemid) {
jQuery($elemid).autocomplete("destroy" );
}
function attach_autocomplete($elemid) {
jQuery($elemid)
.autocomplete({
delay : 250,
minLength : 3,
source : function( request, response ) {
var $thedata = request.term;
jQuery.ajax({
url : myajaxresponder.php,
type : "GET",
data : {
action_id : "autocomplete",
thedata : $thedata
},
error : function (jqXHR, textStatus, errorThrown){
console.log(textStatus + " " + errorThrown);
response("");
},
success : function (result) {
var resultarray = JSON.parse(result);
response(resultarray);
}
});
},
select : function ( event, ui ) {
jQuery($elemid).val(ui.item.value);
return false;
},
})
}
// attach the handlers
jQuery("#myid").focus(function ()
{attach_autocomplete(jQuery(this).prop("id"))});
jQuery("#myid").blur(function ()
{close_autocomplete(jQuery(this).prop("id"))});
Related
As the title says, I'm trying to use ajax to populate a dropdown list from my ApiController and I'm a bit lost. I basically have an entity table that brings back a bunch of department names. After debugging, I know my table is bringing back data as it shows department names coming through. So I think the issue mainly lies within the ajax. When I view the page, the dropdown just says 'nothing selected' and has an empty list. In my ApiController I have:
[RoutePrefix("Api/Request")]
public class NewUserController : ApiController
{
private readonly ZeusEntities _zeus_Entity;
public NewUserController(ZeusEntities zeus)
{
_zeus_Entity = zeus;
}
[Route("Departments")]
[HttpGet]
[CustomApiAuthorize(Roles = UserRole.HR)]
public async Task<IHttpActionResult> GetDepartments()
{
var departments = await _zeus_Entity.DEPARTMENT.Where(z => z.B_DELETE == 0).Select(z => z.S_NAME).Distinct().ToListAsync();
return Ok(departments);
}
}
And in my view, I have:
<div class="form-group col-xs-12 col-sm-4">
<div class="input-group ">
<span class="input-group-addon white">Department</span>
<select class="form-control gray" id="departmentSelect" type="text" </select>
</div>
</div>
Inline:
$.ajax({
type: "GET",
url: "#Url.Action("Departments", "Api/Request")",
data: "{}",
success: function (data) {
var s = '<option value="-1">Please Select a Department</option>';
for (var i = 0; i < data.length; i++) {
s += '<option value="' + data[i].I_PATTERNID + '">' + data[i].S_NAME + '</option>';
}
$("#departmentSelect").html(s);
}
});
Could you please point me in the right direction?
Thanks
So I change the ajax for function to a $.each and realized that I was calling the table column names instead of the variable names I assigned to the data.
$.each(deptList, function (key, department) {
departmentsHtml += "<option value='" + department.DeptId + "'>" + department.Department + "</option>"
});
I feel very silly that I overlooked that bit. Nonetheless, that solved my issue.
I have created a view where when the user selects 2 of the dropdown lists values, an AJAX method is kicked off to populate an additional dropdown list's values
The callback triggers, however I cannot work with the response.
I am probably doing more than one thing wrong, so any help would be greatly appreciated. I am very new to Asp.Net core mvc
My Controller code (simplified - parameters are being used and are working):
public IActionResult GetCodes(string location, string xType)
{
return Json(new Dictionary<string, string> {
{ "","" },
{ "Option1","120" },
{ "Option2","123" }
});
}
My jquery script on the view:
var ddl1val = $("#Location :selected").val().toLowerCase();
var ddl2val = $("#xType:selected").val().toLowerCase();
$.ajax({
type: "GET",
url: "/Ppl/GetCodes",
dataType: 'json',
data: { location: ddl1val, xtype: ddl2val},
success: function (data) {
$("#ddlOptions").empty();
var ops = '<option value=""></option>';
alert(data); //returns [object Object]
alert(data.Key); //returns undefined???
//I need this to work
for (var i = 0; i < data.length; i++) {
ops += '<option value="' + data[i].Key + '">' + data[i].Value + '</option>';
$("#ddlOptions").html(ops);
}
}
console.log(data) shows:
{"": "", Option1: "120", Option2: "123"}
I am not restricted to use JSON return, but it is lighter than xml, so I would prefer using it
Serialising a Dictionary<> to JSON will result in an object like this in your JS:
{
"": "",
"Option1": "120",
"Option2": "123"
}
As such you should not use a for loop to enumerate it. As you're using jQuery you can use $.map() instead. Also note that you don't need to add the empty option as you include that in the response from the MVC endpoint. You also don't need to call empty() as you're overwriting the HTML of the select completely. Try this:
var data = {
"": "",
"Option1": "120",
"Option2": "123"
}
// inside the success callback:
var ops = $.map(data, function(v, k) {
return '<option value="' + v + '">' + k + '</option>';
});
$("#ddlOptions").html(ops);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select id="ddlOptions"></select>
The appended items work perfectly when not including the 2nd Script(which is what gives the listbox a sleek looking listbox with checkboxes in it) - but when I do include it, then it doesnt append the items.
Is there any reason why ?
JQuery:
$("#ddlistcategory").change(function () {
var catItem = $("#ddlistcategory").val();
$("#ddlistaccountitems").empty();
$.ajax({
url: '#Url.Action("GetCategories", "Account")',
dataType: "json",
type: "Post",
data: { "i": catItem },
success: function (data) {
$.each(data, function (key, val) {
//alert(key + " " + val);
$("#ddlistaccountitems").append('<option id="' + key + '">' + val + '</option>');
})
}
});
});
$('#ddlistaccountitems').multiselect({
includeSelectAllOption: false,
allSelectedText: 'No option left ...',
enableFiltering: true,
filterPlaceholder: 'Search for something...'
});
View:
<div class="form-group form-group-sm">
#Html.Label("Items", new { #class = "control-label" })
#Html.ListBoxFor(x => x.SelectedAccountItems, Model.UserItems, new { #class = "form-control", #id = "ddlistaccountitems", #multiple = "multiple" })
</div>
You are calling multiselect outside of your ajax method which is populating the element with the options. As a result you will be initializing it before the ajax has finished, so the issue is most likely that the initialization does not yet have the options to build from.
To fix this, move the initialization into the success method so it will execute after the ajax has finished and all the data that it needs has been created.
Your Ajax call will work asynchronously. That is, the .multiselect will execute before the options appended. .multiselect will hide your actual select and replace it with custom html. So you have to fill it before .multiselect execution. add
async: false
in Ajax call or call
$('#ddlistaccountitems').multiselect()
inside that success function.
I am trying to get the dynamically created TextBox ID into jQuery from Razor view. The IDs are created in HTML as follows:
Product - 1: cartDetails_0__Quantity
Product - 2: cartDetails_1__Quantity
Right now, when I give the above inputs directly to Ajax call, it updates the corresponding rows. As an example:
#if (ViewBag.Cart != null)
{
for (int i = 0; i < cartDetails.Count(); i++)
{
<tr>
<td style="text-align: center;">#Html.TextBoxFor(model => cartDetails[i].Id)</td>
<td style="text-align: center;">#Html.DisplayFor(model => cartDetails[i].IP)</td>
<td style="text-align: center;">#Html.DisplayFor(model => cartDetails[i].ProductName)</td>
<td style="text-align: center;">#Html.DisplayFor(model => cartDetails[i].Price)</td>
<td style="text-align: center;">#Html.TextBoxFor(model => cartDetails[i].Quantity, new { #class = "quantityUpdate", data_id = cartDetails[i].Id })</td>
</tr>
}
}
var url = '#Url.Action("UpdateCart2")';
$(".quantityUpdate").change(function () {
var id = $(this).data('id');
$('.quantityUpdate').each(function (i, item) {
$.post(url, { id: id, quantity: $('#cartDetails_' + 0 + '__Quantity').val() }, function (response) { //cartDetails_0__Quantity - The first TextBox ID
if (response) {
$("#TotalPrice").load(window.location + " #TotalPrice");
}
});
})
alert($('#cartDetails_' + 0 + '__Quantity').val());
});
Is there any way to loop through jQuery to get the dynamically generated TextBox ID in Razor? I've tried the following but doesn't get the value:
$('.quantityUpdate').each(function (i, item) {
$.post(url, { id: id, quantity: $('#cartDetails_' + i + '__Quantity').val() }, function (response) { //cartDetails_0__Quantity - The first TextBox ID
if (response) {
$("#TotalPrice").load(window.location + " #TotalPrice");
}
});
})
Even tried this one but it gets the value of first TextBox only:
$('.quantityUpdate').each(function (i, item) {
$.post(url, { id: id, quantity: $(this).val() }, function (response) { //cartDetails_0__Quantity - The first TextBox ID
if (response) {
$("#TotalPrice").load(window.location + " #TotalPrice");
}
});
})
Note: I am trying to update rows giving input to the TextBoxes with Ajax call. The TextBoxes are in a loop in the view. In this regards, I've to get the IDs of the dynamically generated HTML IDs.
You can use create event of dynamically created elements in order to get their Ids.
But bear in mind to use this you need to use On(). See http://api.jquery.com/on/
See also:
Event binding on dynamically created elements?
In jQuery, how to attach events to dynamic html elements?
PS. If there is a cleaner way to get dynamically created elements I would also be glad to get it :)
Edit. Maybe I was not clear enough . There is no exactly "create" event. You just can hook any actions you need to On()
See also jQuery "on create" event for dynamically-created elements
I have a numerical "badge" value that I'm trying to display on a menu in my MVC 5.1 app.
<span id="myBadge" class="badge menu-badge">#SessionData.MyCount</span>
I have a SessionData class so I don't have to pass around magic strings.
public class SessionData
{
const string MyCountKey = "MyCount";
public static int MyCount
{
get { return HttpContext.Current.Session[MyCountKey] != null ? (int)HttpContext.Current.Session[MyCountKey] : 0; }
set { HttpContext.Current.Session[MyCountKey] = value; }
}
}
The badge is initially populated from a base controller which performs a database call.
SessionData.MyCount = CountThingsFromDatabase();
I use javascript & jquery on the front-end as users modify data. If the count reaches 0, a jquery command hides the "0" badge.
function setBadgeValue(badgeName, count) {
$(badgeName).html(count);
count > 0 ? $(badgeName).show() : $(badgeName).hide();
}
All of this works fine with one exception. When the controller retrieves a count of "0", I'd like to hide the badge from the view in the same manner as the jquery show/hide commands. The front-end jquery piece works wonderfully, but I'm unsure of how to accomplish the same effect from the controller side of things.
Any help would be greatly appreciated.
Update 1:
The views I have utilize Telerik/Kendo objects. This is from a view which displays a Kendo grid. Each grid row has a button that is tied to this method. I'm not sure it would help to post the entire view/controller since most of it is Kendo related.
function addToCart(e) {
// Get the grid data
var grid = $("#Grid").data("kendoGrid");
var dataItem = grid.dataItem(grid.select());
// Add item to the cart
$.ajax({
url: 'Search/AddCart',
data: { itemId: dataItem.ItemId },
success: function () {
$('_MyBadge').html();
$('_Layout').html();
// Update the count
setBadgeValue("#myBadge", 1);
},
error: function (xmlHttpRequest, textStatus, errorThrown) {
alert('Failed to add item #' + dataItem.itemId + ' to your cart.\nStatus: ' + textStatus + '\nError: ' + errorThrown);
}
});
}
How about doing this on the view?
#if (SessionData.MyCount == 0)
{
<span id="myBadge" class="badge menu-badge" style="display: none;">#SessionData.MyCount</span>
}
else
{
<span id="myBadge" class="badge menu-badge">#SessionData.MyCount</span>
}
No need to use the controller in any way, just hide your badge initially in the view if your count is zero.
<span id="myBadge" class="badge menu-badge" style="display: #(SessionData.MyCount > 0 ? "block" : "none");">#SessionData.MyCount</span>