Scoop...
I have a drop down list that might not display a particular option you're looking for. I added a button with pop up modal to type in a field you want to add to the drop down list. It functions perfectly, but I need to add an ajax postback method to refresh the list after the user hits enter. I don't want to refresh the whole page, just the list. any help?
Controller:
public ActionResult AddLeadSource()
{
return View();
}
[HttpPost]
public ActionResult AddLeadSource(string name)
{
LeadSource ls = new LeadSource();
ls.Name = name;
db.LeadSources.Add(ls);
db.SaveChanges();
return Json(new { success = true });
}
JS
<script>
$("#AddNew").change(function () {
var name = $("#Name").val();
// var order = $("#DisplayOrder").val();
$.ajax({
type: 'POST',
dataType: 'json',
cache: false,
url: '/Admin/LeadSource/AddLeadSource',
data: { name: name },
success: function (response) {
//alert("Success " + response.success);
$('#FollowUpNotes').kendoWindow('destroy');
// Refresh the DropDown <-- Heres where I need some help!
},
error: function (jqXHR, textStatus, errorThrown) {
alert('Error - ' + errorThrown);
}
});
});
In your success function of your Ajax call add this:
$("IdOfDropDownList").data("kendoDropDownList").dataSource.read();
In this way your dropdownlist will call the read function and reload all data. I assumed that your dropdownlist is binding throught read call.
I highly recommend looking at jQuery UI's autocomplete widget. That said,
$('#YourDropDownID option').remove(); //this will remove all option elements inside the <select id="YourDropDownID">
Then you just need to build new ones based on the response data,
for (var o in data) {
if (data[o].Value != undefined) {
$('#YourDropDownID').append('<option value="' + data[o].Value + '">' + ("" + data[o].Display) + '</option>');
}
}
I do this inside the .done() callback of my AJAX:
.done(function (data) {
//above code
}
Depending on the nature of the data you are sending back you may need to loop through it differently. Mine is an array of objects with a Value and Display properties (in my case, account numbers and account names).
//server side controller
var query = #"
Select
SubString([mn_no], 0, 6) As Value,
RTRIM([acct_desc]) As Display
From [some_table]";
return con.Query(query, new { AccountNumber = accounts.Select(x =>
{
return new { Value = x.Value, Display = x.Display };
});
Related
I have a drop down list and I want the value to be sent to the controller when an option is selected,replaceing the returned values in the desired inputs
Html Inputs :
<input type="text" class="form-control js-inputs" id="microchipcode">
<input class="form-control js-inputs" id="fa-horse">
<input type="text" id="fa-fatherhorse" class="form-control js-inputs">
Html DropDown:
$('.js-selected-item').change(function () {
let Value = $(this).val();
$.ajax({
data: { value: Value },
Url: "/Horse/GetHorseByMcode",
type: "post",
success: function (data) {
}
});
});
Controller :
public async Task<IActionResult> GetInfoHorse(string value)
{
var horse = await _coach.GetHorseByMcode(value);
if (horse != null)
{
return Json(horse);
}
return NotFound();
}
Query :
public async Task<Horse> GetHorseByMcode(string value)
{
return await _context.Horses.SingleAsync(h => h.MicrochipCode == value.Trim());
}
If you want to put a value into an input via js, add an ID to the inputs and do the following:
JS:
document.getElementById('//inputId').value = '';
Jquery:
("#//inputId").val("");
How do I access the data inside the object?
You can check the request and response in f12 developer tool Network tab, like below.
and implement frontend code to populate input field(s) in ajax success callback function based on your actual returned data.
For example:
success: function (data) {
$("#fa-fatherhorse").val(data.fatherHorse);
//populate other inputs based on your actual returned data
How to replace Drop Down list ?
If you want to dynamically set the selected value/option of the dropdown, you can try:
$("#dropdown_id_here").val(value_of_selected_option);
If you want to dynamically append <option> to your dropdown, you can try:
var newoption = "<option value='" + option_val + "'>" + option_text + "</option>";
$("#dropdown_id_here").append(newoption);
I am working on a project in Visual studio using MVC. I am trying to reload a div after a btn is clicked and data has been posted to the controller dynamically. I use an Ajax post and return a JSONresult. The code for posting looks like this:
<div id = "DelUser">
#using (Html.BeginForm(null, null, FormMethod.Post, new { id = "Dform" }))
{
<label> Select User(s) to Delete: </label>
#Html.ListBox("Users", ViewBag.Users as MultiSelectList,
new { #class = "chzn-select", #style = "width:250px; height:350 px" })
}
<button class="btn btn-primary dropdown-toggle" id="Button1" type="button" onclick="DeleteUsers()"> Delete Selected </button>
</div>
<script>
function DeleteUsers() {
var myList = []
$("#Users > option:selected").each(function () {
myList.push($(this).val());
});
jQuery.ajax({
type: 'post',
dataType: 'json',
contentType: "application/json; charset=utf-8",
url: 'DeleteU',
data: JSON.stringify(myList),
success: function (data) {
$('#msgbx2').html(data.msg);
//here I am trying to refresh the div after the post but it fires every second
$('#DelUser').html('/Home/DeleteUser');
},
failure: function (errMsg) {
$('#msgbx2').html(data.msg);
}
});
return false;
}
The name of the controller is DeleteUser and the JSONresult controller is DeleteU.
I am trying to do this so that the dropdownlist updates after I delete the selected users. If there is another way to dynamically update this div, any information on that would be good to know too. Thank you in advance.
Here are the Controllers as well:
[HttpGet]
public ActionResult DeleteUser()
{
List<string> u = new List<string>();
object[] users = data.getDataFrmDB("Select username From `users`;");
if (users != null)
{
foreach (object[] user in users)
{
u.Add((string)user[0]);
}
}
ViewBag.Users = new MultiSelectList(u, "Username");
return View();
}
[HttpPost]
public JsonResult DeleteU(List<string> Users)
{
bool good = false;
if (Users != null)
{
foreach (string user in Users)
{
string ins = "DELETE FROM `xcal-server`.`users` WHERE username='"+user+"';";
good = data.insert_update_delete_DB(ins);
List<string> u = new List<string>();
object[] users = data.getDataFrmDB("Select username From `users`;");
if (users != null)
{
foreach (object[] usera in users)
{
u.Add((string)usera[0]);
}
}
ViewBag.Users = new MultiSelectList(u, "Username");
if (good == true)
{
ViewBag.error = "You have successfully deleted user";
}
else
{
ViewBag.error = "There was an issue removing user";
}
}
return Json(new { msg = "You have Successfully deleted Users " });
}
return Json(new { msg = "the passwords entered do not match" });
}
This is just a section of my main page that has other action functions/controllers in it which is why i did not originally post the controllers
You can simply update the existing listbox by removing the currently selected items. Start by removing onclick="DeleteUsers() from the button and use Unobtrusive JavaScript. Since you do not appear to have a POST method for DeleteUser() or a submit button, you may as well also replace #using (Html.BeginForm(...)) with just <form> elements. The script will then be
$('#Button1').click(function () {
var selected = $('#Users option:selected'); // store the selected users
if (selected.length == 0) {
return; // no point making a post
}
var users = [];
$.each(selected, function (index, item) {
users.push($(this).val());
})
$.ajax({
type: 'post',
dataType: 'json',
url: '#Url.Action("DeleteU", "yourControllerName")', // always use Url.Action to generate your url's
data: { users: users },
traditional: true,
success: function () {
// remove the currently selected options
selected.remove();
}
});
})
However a lot of the code in your controller does not make sense. Your adding values to ViewBag and even creating a SelectList but your not returning a view (your returning json), so all that is lost. And even if you were returning a view, your loop keeps overwriting the value of ViewBag.error so that only the last value would be set. Ideally, you should be calling a service to delete the users by passing the user name (or a collection of user names so that they are all deleted in a transaction). But based on you current code, you controller method can be
[HttpPost]
public JsonResult DeleteU(List<string> Users)
{
if (Users == null)
{
// throw an error that can be caught in the ajax error handler
}
List<string> deletedUsers = new List<string>();
foreach (string user in Users)
{
string ins = "DELETE FROM `xcal-server`.`users` WHERE username='"+user+"';";
if (data.insert_update_delete_DB(ins))
{
deletedUsers.Add(user);
}
}
return Json(deletedUsers);
}
and then the ajax success callback
success: function (data) {
$.each(data, function(index, item) {
// remove each item that was successfully deleted in the controller
$('#Users option:contains("' + item + '")').remove();
}
}
i think you need to add a $(document).ready(function(){}); around your script
I am using MVC.
I am having two drop down and one change of 'primaryspec' the 'primarysubspec' should get loaded.
Everything is working fine for passing values to controller and it got saved to DB.
When I am trying to retrieve the saved details,'primarysubspec' saved values are not getting displayed.
But displaying save data for 'primarySpec'.
Here is my .cshtml code:
#Html.DropDownListFor(m => m.PSpec, Model.PSpec, new { id = "ddUserSpec", style = "width:245px;height:25px;", data_bind = "event: {change: primaryChanged}" }, Model.IsReadOnly)
#Html.DropDownListFor(m => m.PSubspec, Model.PSubspec, new { id = "ddUserSubSpec", style = "width:245px;height:25px;", data_bind = "options: primarySubSpec,optionsText: 'Name',optionsValue: 'Id'" }, Model.IsReadOnly)
Here is my JS Code to retrieve the values for :
this.primarySubSpec = ko.observableArray([]);
this.primarySpecChanged = function () {
var val = $("#ddetailsPrimarySpec").val();
primarySubStartIndex = 0;
primarySubSpecialityUrl = '/PlatformUser/GetSpecandSubSpec?primarySpe=' + val+//model.primarySpecID() +'&secondarySpec=';
loadPrimarySubSpec();
};
function loadPrimarySubSpec() {
$.ajax({
type: 'GET',
url: primarySubSpecUrl,
contentType: 'application/json; charset=utf-8',
dataType: 'json',
processdata: false,
cache: false,
success: function (data) {
primarySubSpec = [];
model.primarySubspec('0');
try {
if (data.length == 0) {
primarySubSpeacId.empty();
}
model.primarySubSpec(data);
},
error: function (request, status, error) {
primarySubSpeacId.prop("disabled", true);
}
});
}
Everything is working fine,but facing issue only while displaying the saved values from the DB.
Showing fine for 'primarySpec'
The values showing empty for 'PrimarySubSpec' instead of saved values in dropdown.
Please let me know what is the issue how can i show the saved value as selected value in 'primarySubSpec'dropdown.
The Problem:
when you load the page to view saved values, the change event is never called.
Why:
When your page is loaded with saved values, the select box has the saved value selected before knockout knows anything about it. Hens the change event isn't called.
Simplest solution:
change the primarySpecilaityChanged as follows
this.primarySpecilaityChanged = function () {
var val = $("#ddUserDetailsPrimarySpeciality").val();
if(val){
primarySubStartIndex = 0;
primarySubSpecialityUrl = '/' + NMCApp.getVirtualDirectoryName() + '/PlatformUser/GetSpecialitiesandSubSpecilaities?primarySpeciality=' + val+//model.primarySpecialityUID() +'&secondarySpeciality=';
loadPrimarySubSpecilaities();
}
};
then call primarySpecilaityChanged function after you call ko.applyBindings.
var viewModel = new YourViewModel();
ko.applyBindings(viewModel);
viewModel.primarySpecilaityChanged();
When my MVC5 View loads, I am filling a list for a DropDown on the View and setting the View to only display model records that have a [verified_date] field value older than the cutoff, by default 3 Months:
private InventoryTrackerContext db = new InventoryTrackerContext();
// GET: VerifyAssets
public async Task<ActionResult> Index()
{
List<SelectListItem> intervalList = new List<SelectListItem>();
intervalList.Add(new SelectListItem { Text = "Month", Value = "Month" });
intervalList.Add(new SelectListItem { Text = "Day", Value = "Day" });
intervalList.Add(new SelectListItem { Text = "Year", Value = "Year" });
var cutoffDate = DateTime.Now.AddMonths(-3);
var iNV_Assets = db.INV_Assets.Where(i => i.verified_date < cutoffDate).Include(i => i.Location).Include(i => i.Manufacturer).Include(i => i.Model).Include(i => i.Status).Include(i => i.Type).Include(i => i.Vendor);
ViewBag.intervalList = intervalList;
return View(await iNV_Assets.ToListAsync());
}
Now what I'm trying to implement, is allow users to specify an interval value and interval setting (values 1-31, and [Month], [Day], [Year]):
#Html.DropDownList("NumberValueSelection", Enumerable.Range(1, 31).Select(x => new SelectListItem { Text = x.ToString(), Value = x.ToString() }))
#Html.DropDownList("intervalList")
<span class="glyphicon glyphicon-refresh"> REFRESH</span>
When users click the [REFERSH] button (hyperlink), I want to refresh the view based on user specifications:
SCRIPT:
function newCutoffDate() {
var _value = document.getElementById("NumberValueSelection").value;
var _interval = document.getElementById("intervalList").value;
var data = { value: _value, interval: _interval };
$.ajax({
type: "POST",
dataType: "JSON",
url: '#Url.Action("NewCutoffDateInterval", "VerifyAssets")',
data: data,
success: function (resp) {
alert("Sucess! Value: " + resp.value + " | Interval: " + resp.interval);
},
error: function (resp) {
alert("Error! Value: " + resp.value + " | Interval: " + resp.interval);
}
})
}
CONTROLLER ACTION:
[HttpPost]
public async Task<ActionResult> NewCutoffDateInterval(int value, string interval)
{
var cutoffDate = DateTime.Now.AddMonths(-3);
if (interval == "Month")
{
cutoffDate = DateTime.Now.AddMonths(-value);
}
else
{
if (interval == "Day")
{
cutoffDate = DateTime.Now.AddDays(-value);
}
else
{
if (interval == "Year")
{
cutoffDate = DateTime.Now.AddYears(-value);
}
}
}
var iNV_Assets = db.INV_Assets.Where(i => i.verified_date < cutoffDate).Include(i => i.Location).Include(i => i.Manufacturer).Include(i => i.Model).Include(i => i.Status).Include(i => i.Type).Include(i => i.Vendor);
return View(await iNV_Assets.ToListAsync());
}
This however is not working. When I click the [REFRESH] button (hyperlink), my function executes and my controller action gets called, but the View does not refresh. All that occurs is that I get a return of "Error! Value: undefined | Interval: undefined".undefined` makes sense considering I'm not returning anything, but why is the View not refreshing?
$.ajax({ doesn't modify the DOM nor the window.location. It is an asynchronous request, and therefore happens "behind the scenes" so to speak. No navigation takes place, and the page/DOM is not modified without you explicitly doing so.
If you want the entire page to refresh, you have a couple of options.
Navigation via standard href
Make your link point to a valid href so when they user clicks it, they will be navigated. Use javascript as the user modifies selections to modify the href encoding parameters as query string values. You get the "Refresh" effect just by pointing the URL to the same page, but dynamically updating the href as the user makes selections before hitting refresh. When the user clicks the link, the controller should parse the parameters, and return the same page with new filters applied.
<a href='/VerifyAssets/NewCutoffDateInterval?someParameter=someValue'>Refresh</a>
Navigation via window.location
Keep you <a> as is, but modify your javascript such that instead of making an ajax request, you build a URL as described above, and set it as window.location, causing the page to navigate to the new URL:
// assume you build part after ? dynamically
var url = '/VerifyAssets/NewCutoffDateInterval?someParameter=someValue';
window.location.href = url;
Refreshing partial page
If you create an action that returns a partial view, you can refresh a portion of the page by replacing the content of some element with what is returned:
success: function (resp) {
$('#idOfSomeDiv').html(resp); // replace contents with returned
},
If the request points to a partial view, then resp will be the HTML fragment representing the partial view, and we need to take that and insert it somewhere on the page, which is what $('#idOfSomeDiv').html(resp); does.
There's lots of nuances to each of these approaches that's covered pretty thoroughly elsewhere, so I'm not going to get into that. Some versions of jquery for example require you parse the response before setting it in the DOM. I'll leave it up to you to research your method of choice further.
You're returning a ViewResult to a Javascript call. This won't refresh the view. The better option is to make your existing Controller route an HTTP GET that your refresh link reuses and passes the parameters set in your interface as query string parameters.
EDIT: When I've done this before, I've taken the HTML being returned from async route, and appended it into the DOM. This is different because you're looking to replace the DOM, but it's the same basic idea.
Here's some example Javascript that appends AJAX retrieved HTML into the page
window.EditableList = function (containerSelector) {
var $container = $(containerSelector);
var $list = $container.find("ol").eq(0);
$container
.off(".editable-list")
.on("click.editable-list", "a.add-editor-row", function (e) {
$.ajax({
url: e.target.href,
cache: false,
success: function (html) {
$list.append(html);
ShowHideIcons($("#question-style-dropdown").val());
}
});
return false;
})
.on("click.editable-list", "a.delete-editor-row", function (e) {
$(e.target).parents('li.editor-row').remove();
return false;
});
};
sample controller action
public ActionResult AddFragment()
{
var viewModel = new FragmentViewModel(parameters);
return PartialView("Fragment", viewModel);
}
I'm testing MVC for a demo and I managed to scrap together some pieces but now I am having trouble with an Html.ActionLink. The intent is to present the user with a series of dropdownlists that they must select before the ActionLink is shown. To do that I've copied some JQuery to hide/show my dropdownlists (as selections are made) and the ActionLink. I added an alert to my JQuery to check my values and via the alert it all looks good. But if I debug the controller the parm values are defaulted to 0. I'm not sure what code to include but I will try to include the relevant parts. I think it's something basic.
Here are the dropdown lists and ActionLink.
#Html.DropDownListFor(m => m.selected_env_ID, new SelectList(Model.Environments, "env_ID", "env_DESC"), "*Select an environment")
#Html.DropDownListFor(m => m.selected_app_ID, new SelectList(Model.Applications, "app_ID", "app_DESC"), "*Select an application",new { #hidden = "hidden" })
#Html.DropDownListFor(m => m.selected_job_ID, Enumerable.Empty<SelectListItem>(), "*Select a job", new { #hidden = "hidden" })
#Html.ActionLink("Submit", "Submit", new { id = Model.selected_job_ID, envid = Model.selected_env_ID }, new {id = "lnkSubmit" })
Here is the convoluted JQuery to hide/show and fill the cascading dropdowns.
<script>
$(document).ready(function ()
{
//Dropdownlist Selectedchange event
$("#selected_app_ID").change(function () {
var id = $('#selected_app_ID').val(); // id value
if (id == 0) {
$('#selected_job_ID').hide();
} else {
$('#selected_job_ID').show();
$("#selected_job_ID").empty();
$.ajax({
type: 'POST',
url: '#Url.Action("SelectJobs")',
dataType: 'json',
data: { id: $("#selected_app_ID").val() },
success: function (jobs) {
// jobs contains the JSON formatted list of jobs passed from the controller
$("#selected_job_ID").append('<option value=0>*Select a job</option>');
$.each(jobs, function (i, job) {
$("#selected_job_ID").append('<option value="'
+ job.job_ID + '">'
+ job.job_DESC + '</option>');
});
},
error: function (ex) {
alert('Failed to retrieve jobs.' + ex);
}
});
}
return false;
});
//ddl select change
$("#selected_env_ID").change(function () {
var name = $('#selected_env_ID option:selected').text(); //Item1
var id = $('#selected_env_ID').val(); // id value
if (id == 0) {
$('#divSubmit').hide();
$('#selected_app_ID').hide();
$('#selected_job_ID').hide();
} else {
$('#selected_app_ID').show();
}
});
//ddl select change
$("#selected_job_ID").change(function () {
var name = $('#selected_job_ID option:selected').text(); //Item1
var id = $('#selected_job_ID').val(); // id value
var envid = $('#selected_env_ID').val(); // id value
if (id == 0) {
$('#divSubmit').hide();
} else {
$('#divSubmit').show();
alert("envid=" + envid + " jobid=" + id);
}
});
}); // end document ready
</script>
My controller has this and id and envid end up being 0:
public ActionResult Submit(int id = 0,int envid = 0) {
If I need to include something else just let me know.
Here is the method that fills the job dropdown list. This works without issues. It's the Html.ActionLink call to Submit that fails to include the parameters.
public JsonResult SelectJobs(int id)
{
db.Configuration.ProxyCreationEnabled = false;
IEnumerable<t_job> jobs = db.t_job.Where(j => j.app_ID == id).ToList();
return Json(jobs);
}
Your link
#Html.ActionLink("Submit", "Submit", new { id = Model.selected_job_ID, envid = Model.selected_env_ID }, new {id = "lnkSubmit" })
is rendered on the server side before you make any selection in the dropdowns. If the initial values of selected_job_ID and selected_env_ID are zero or null, then those values will be passed to the controller (have a look at the rendered html).
If you want to pass the values selected in you drop downs, you could either modify the links href attribute in the drop down change events, or create a button instead of a link, and do a redirect in the buttons click event based on the dropdown values.
You need to use JSON.stringify():
data: JSON.stringify({ id: $("#selected_app_ID").val() }),