I'm currently receiving an error whilst trying to fill a cascading select list who's javascript function is triggered by the on change of the previous list however the every time the controller returns the json object back to Ajax callback, Google Chrome DevTools is throwing the error:
DevTools was from the page
Once page is reloaded, DevTools will automatically reconnect
I have tried to enable logs and run Chrome using the flags however nothing is ever logged, nothing is saved in the logs in the Network tab either.
I have tested populating the select tag through adding a submit button to the first dropdown and calling/ populating the second dropdown that way and that seems to work fine. Is there any reason that using onchange on the Html.DropDownListFor() would cause DevTools to throw this error?
The PartialView containing the code (I have added both techniques I have used):
<div class="form-group">
<label>Select Country</label>
<!-- This works in filling the second dropdownlist. -->
#Html.DropDownListFor(m => m.SelectedCountry, new SelectList(Model.Country, "FieldID", "Value"), new { #id = "_ddlCountries", #class = "fr-select" })
<button type="submit" onclick="javascript: GetCities()">Test</button>
<!-- ********************************************** -->
<!-- This does not work in filling the second dropdown -->
#Html.DropDownListFor(m => m.SelectedCountry, new SelectList(Model.Country, "FieldID", "Value"), new { #id = "_ddlCountries", #class = "fr-select", onchange="javascript: GetCities()" })
<!-- ********************************************** -->
</div>
<div class="form-group">
<label>Select City</label>
<select class="fr-select" id="_cities"></select>
</div>
Both get into the javascript function below but the onchange throws the DevTools message/ error:
function GetCities() {
debugger;
var ddlText = $('#_ddlCountries option:selected').text();
$.ajax({
url: '#Url.Action("GetCities", "Home")',
type: 'POST',
data: JSON.stringify(ddlText),
contentType: 'Application/json',
success: function (result) {
debugger;
//Create a markup for a select
var markup = "";
//Populate the markup
for (var i = 0; i < result.length; i++) {
markup += "<option Value=" + result[i].FieldID + ">" + result[i].Value + "</option>";
}
//Populate dropdown with value
$("#_cities").html(markup).show();
}
})
}
Controller action:
public ActionResult GetCities([FromBody] string ddlText)
{
List<FieldMap> cities = new List<FieldMap>();
cities.Add(new FieldMap
{
FieldID = 0,
Value = "-- Please Select a City --"
});
foreach (var city in _uploadedFileModel.cities.Where(x => x.name == ddlText).OrderBy(x => x.city.name))
{
cities.Add(new FieldMap
{
FieldID = cities.Select(x => x.FieldID).Max() + 1,
Value = city.name
});
}
return Json(cities);
}
This works using MVC framework but for some reason it doesn't with Core. Is there any reason why the onchange would be triggering this error?
Related
I'm new to C#, JS, jQuery, etc.
For a schoolproject I'm building a cinema-website with ASP.NET and C#.
I have come to the point that I think I'm close to the answer, but I can't figure it out.
What is the problem?
At the Index-page of the website the customer can pick a movie to go to the next screen to buy the tickets. There he needs to pick a moment of the movie from a dropdownmenu. The dropdownmenu-code looks like this:
<div class="form-group" style="width: 30%">
#Html.LabelFor(m => Model.Showtime, new { #class = "control-label col-md-2" })
<div>
#Html.DropDownListFor(m => Model.Showtime!.StartAt, new SelectList(Model.ShowList, "Value", "Text"), "Select show", new { #class = "form-control", id = "showList" })
</div>
</div>
I've created a jQuery function that gets the picked Showtime from the dropdownmenu.
This function looks like this:
<script>
$("#showList").change(function() {
var selectedVal = $(this).val();
$.ajax({
type: 'POST',
dataType: 'JSON',
url: '/Orders/GetPickedShowtime/',
data: {showTimeId: selectedVal},
success:
function(response) {
response = JSON.stringify(response)
$('#testShowtime').text(response)
},
error:
function(response) {
console.log("ERROR: ", response)
}
});
})
</script>
In the controller I wrote a function to get the picked Showtime object from the database:
public ActionResult<Showtime> GetPickedShowtime(int showTimeId) {
var show = _context.Showtime!
.Where(s => s.Id == showTimeId);
return Json(show);
}
I used this code: $('#testShowtime').text(response) in my jQuery to test the function in my View with: <h4 id="testShowtime"></h4>. It works. It gives a Array back to the View, like:
[{"id":6987,"startAt":"2022-03-13T18:00:00Z","hallId":3,"movieId":1,"hall":null,"movie":null}]
GREAT! The function seems to work. But what I want to do now is to get the Object from this Json-string into a C# variable. If the customer selects a showtime and some tickets, a button brings them to the next page where the seatselection begins. So the variable with the picked Showtime needs to go there by clicking a button.... And now I'm stuck.
Could someone help me out of this puzzle? I'll buy you a beer :P
You can use Session variable to store your StoreTime on the server itself. AJAX is used to update a portion of the page without reloading the entire page and in your case, you are unnecessarily complicating things. You can do the following:
In your method, define a Session variable which is always updated when the user selects from the dropdown:
public ActionResult<Showtime> GetPickedShowtime(int showTimeId) {
var show = _context.Showtime!.Where(s => s.Id == showTimeId);
if(show != null)
{
Session["myCurrentShow"] = show;
}
return Json(show);
}
Now once your Session is defined, you can access it on your next ActionMethod. I am giving an example how you would use this Session variable on your last step:
public ActionResult ConfirmShowTime() {
if(Session["myCurrentShow"] != null)
{
Showtime showtime = new Showtime();
//Cast your session here to get the values
showtime = (Showtime)Session["myCurrentShow"];
}
// Your logic
return View();
}
In certain cases, usually after values have been cached from an initial search, I cannot get the mdb_autocomplete drop down to close on a single click. I often have to double click on my selection to get it to close. I am dynamically populating the values in the drop down via an Ajax call to a service method via and controller action method that searches the active directory for the first 30 name values. No call back occurs until a user enters at least 3 values into the mdb_autocomplete selection box. The callback and population of the drop down is working very well, but the click event following the selection of a value often will not close the dropdown. Additionally, we are being forced to use mdb boostrap over the normal bootstrap library. I have included the view, service, and typescript code that is being used to generate and populate the drop down.
View:
<div class="form-group">
<label class="font-weight-bold" for="RequestorSearchInput">Requestor</label>
<input type="text" id="RequestorSearchInput" name="RequestorSearchInput" class="form-control mdb-autocomplete" />
<span id="loading_data_icon"></span>
</div>
Service Method:
public List<string> GetRequestor(string aRequestor)
{
IEnumerable<Dictionary<string, string>> requestorNames;
using (ActiveDirectoryService service = new ActiveDirectoryService(<LDAP Domain Name>))
{
string[] propertiesToLoad = new string[] { "displayName" };
//requestorNames = service.SearchByPartialUsername(aRequestor, propertiesToLoad).Take(30).Union(service.SearchBySurname(aRequestor, propertiesToLoad).Take(30));
requestorNames = service.SearchBySurname(aRequestor, propertiesToLoad).Take(30);
}
return requestorNames.SelectMany(x => x.Values).Where(y => y.IndexOf(",", StringComparison.Ordinal) >= 0).Distinct().ToList();
}
TypeScript:
private handleRequestorSearch() {
let options: string[] = new Array();
// #ts-ignore
let searchval = $("#RequestorSearchInput").val().length;
if (searchval >= 3) {
$.ajax({
url: main.getControllerHREF("GetRequestor", "Search"),
method: "POST",
data: {
requestor: $("#RequestorSearchInput").val()
},
async: false,
dataType: "json",
success: function (names) {
$.each(names, function () {
options.push(this);
});
// #ts-ignore
$("#RequestorSearchInput").mdb_autocomplete({
data: options
}).select(function () {
$("#RequestorSearchInput").focus;
});
}
});
}
}
I have the following functionality: A user registers a series of data in a form, after sending the form and saving it in the database, it is redirected to a second form, where it must load the rest of the information, it is possible that in this second form, contains a lot of values of the first form, but this is not always the case, that is why in this second form there is a button that allows "copy" the data of the first form, to reduce data entry.
As I did?
I created a main view, where the form is loaded as a partial view with the empty model fields, so that the user can enter the information if it is not the same as the first form
Main View:
<div id="partialView">
#Html.Partial("_CreatePartialResponsable", Model)
</div>
In the form that contains the partial view, there is a dropdowlist that is filled through a web service. This dropdow is filled correctly when loading the blank form, the first time.
DropDownList in the partial view
<div class="form-group col-md-6">
#Html.LabelFor(model => model.SeguroNombre, htmlAttributes: new { #class = "titulocampo" })
<select id="SeguroNombre" name="SeguroNombre" class="form-control"><option value=""></option></select>
#Html.ValidationMessageFor(model => model.SeguroNombre, "", new { #class = "text-danger" })
</div>
With this script, the dropdowlist is loaded, I call it from the main view in the document.ready event (it's works perfectly)
function llenaDropDownSeguros(url, valor) {
var data = { nombre: valor };
$.post(url, data).done(function (data) {
if (data.isError) {
muestraError(data.Titulo, data.Mensaje);
} else {
for (var i = 0; i < data.length; i++) {
$('#SeguroNombre').append('<option value=' + data[i].codigoSeguro + '>' + data[i].descripcion + '</option > ');
}
}
});
};
If the user wants to "copy" the information of the previous form, press a button that executes the following function js to go to the server, search the data and return the same partial view, but with the corresponding fields loaded. Re render?
Script to "copy" data
function loadPartial(url, valor) {
$("#esperar").show();
var data = { cedula: valor };
$.post(url, data).done(function (data) {
if (!data.isError) {
$("#esperar").hide();
$("#partialView").html(data);
} else {
$("#esperar").hide();
muestraError(data.Titulo, data.Mensaje);
}
}).fail(manejarErrorAjax);
};
What is the problem?
After the copy button is pressed and the partial view is reloaded with the "copied" data, the dropdownlist items are no longer there. I understand that they are lost, because of course, when doing a partial view reloaded, that dropdown comes empty, that I understood. What I do not understand is because, after reloading that partial view, there is no way I can fill the dropdowlist again. By test I made a change and in the click event of the ddl, I called the loadPartial function to see if it worked, but even though in the browser console, it is seen that the function is executed and the data object takes 94 values, these they are not loaded to the dll.
Can you help me with this problem?
we are implementing an MVC solution using Telerik controls and
we have some problems refreshing the list of a Telerik ComboBox. Pratically we need to refresh the list of available values of a ComboBox every time the value selected in another ComboBox is changed. Below is our scenario:
Main ComboBox has a list of string values and we added an event;
Detail ComboBox has a list of values that depends on what is chosed from Main ComboBox;
When the event on Main ComboBox is fired the javascript calls an action in Controller;
The controller refresh the content of List02 (the datasource binded in ComboBox02)
Actually it runs all correctly but the Detail ComboBox does not refresh. What is wrong or missed?
Many Thanks for help
Main ComboBox:
<%=Html.Kendo().DropDownListFor(ourModel => ourModel.ModelPK)
.HtmlAttributes(new { #class="textboxDetails" })
.Name("combo01")
.BindTo((IEnumerable<ModelObject>)ViewData["List01"])
.DataTextField("descriptionText")
.DataValueField("valueID")
.Value(ourModel.ModelPK.ToString())
.Events(e =>
{
e.Select("onSelect");
})
%>
Detail Combobox:
<%=Html.Kendo().DropDownListFor(ourModel => ourModel.secPK)
.HtmlAttributes(new { #class="textboxDetails" })
.Name("combo02")
.BindTo((IEnumerable<ModelObject>)ViewData["List02"])
.DataTextField("descriptionText")
.DataValueField("valueID")
.Value(ourModel.Model02PK.ToString())
%>
Javascript on aspx page:
function onSelect(e) {
var dataItem = this.dataItem(e.item);
var itemPK = dataItem.valueID;
$.ajax({
type: 'POST',
url: '/controller01/action01',
data: "{'sentPK':'" + sentPK + "'}",
contentType: 'application/json; charset=utf-8',
success: function (result) {
},
error: function (err, result) {
alert("Error" + err.responseText);
}
});
}
Controller action:
[AcceptVerbs(HttpVerbs.Post)]
public void action01(model01 editModel, int sentPK)
{
//View data loads correctly
}
I do not think updating second combobox with ViewData will work in scenario:
.BindTo((IEnumerable)ViewData["List01"])
For the very first time when the page is rendered the value stored in ViewData object is used to fill the combobox but then onSelect all you are doing is, making an AJAX call to server. Server updates the ViewData object but as the combo box is already loaded with initial data, it will not be refreshed with new data.
You will have to refresh the second combobox on selection change event for first combo box.
Option 1:
Add following lines in your onSelect() success:
var combobox = $("#combo02").data("kendoComboBox");
combobox.dataSource.data(result);
Option 2:
Bind datasource of second combobox with server:
#(Html.Kendo().ComboBox()
.Name("products")
.HtmlAttributes(new { style = "width:300px" })
.Placeholder("Select product...")
.DataTextField("ProductName")
.DataValueField("ProductID")
.Filter(FilterType.Contains)
.DataSource(source => {
source.Read(read =>
{
read.Action("GetCascadeProducts", "ComboBox")
.Data("filterProducts");
})
.ServerFiltering(true);
})
.Enable(false)
.AutoBind(false)
.CascadeFrom("categories")
)
For a working example, refer this link.
I have an Editor Template which contains a table row with (among other stuff) a dropdown/combobox to select a currency. This edit template is shown many times on the same View and it's possible for a user to add these rows as many times as he wants.
I want changes on a row's dropdown to reflect in an EditorFor (the currency's rate) on the same row, so I've added a onchange html parameter:
<td>
#*#Html.LabelFor(model => model.Currency)*#
#Html.DropDownListFor(model => model.Currency, new SelectList(Model.CurrencyList, "Code", "Code"), new { onchange = "updateCurrency(this)" })
#Html.ValidationMessageFor(model => model.Currency)
</td>
My javascript function makes an ajax call to retrieve the rate for the selected currency:
function updateCurrency(elem) {
alert("Currency changed!")
$.ajax({
type: "GET",
url: "Currency?code=" + elem.value,
success: function (msg) {
// The Rate field's Id:
var RateId = "#Html.ClientIdFor(model=>model.Rate)" // // Halp, problem is here!
document.getElementById(RateId).value = msg;
}
});
}
My problem is that
var RateId = "#Html.ClientIdFor(model=>model.Rate)"
has that Html helper which is server-side code. So when i view the page's source code, the javascript code is replicated (once for each row) and all the var RateId = "#Html.ClientIdFor(model=>model.Rate)" are pointing to the most recently added column's EditorFor.
Probably my way of attempting to solve the problem is wrong, but how can I get my javascript code to update the desired field (i.e. the field in the same row as the changed dropdown list).
I believe that one of the problems is that I have the javasript on the Editor Template, but how could I access stuff like document.getElementById(RateId).value = msg; if I did it like that?
Thanks in advance :)
Figured it out. Hoping it helps somebody:
In my view:
#Html.DropDownListFor(model => model.Currency, new SelectList(Model.CurrencyList, "Code", "Code"), new { #onchange = "updateCurrency(this, " + #Html.IdFor(m => m.Rate) + ", " + #Html.IdFor(m => m.Amount) + ", " + #Html.IdFor(m => m.Total) + ")" })
In a separate JavaScript file:
function updateCurrency(elem, RateId, AmountId, TotalId) {
var cell = elem.parentNode // to get the <td> where the dropdown was
var index = rowindex(cell) // get the row number
// Request the currency's rate:
$.ajax({
blah blah blah .........
(RateId[index - 1]).value = 'retreived value'; // Set the rate field value.
});
}
Seems to be working so far.