How to set the same dropdown across multiple forms from ajax - javascript

I have multiple instances of the same form within different accordion elements. Each form represents a different project. I am trying to populate a dropdown on the form with a list of managers that is stored dynamically. I can only get the first dropdown instance to populate, and not the rest. How do I get all the instances of the manager dropdown to populate?
HTML
#foreach (Project project in Model.Projects)
{
<div class="accordion-item">
<h2 class="accordion-header" id="#("heading"+project.Key)">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" aria-expanded="false">
<b> #project.Number- </b>: #project.Name
</button>
</h2>
<div class="accordion-body">
<form>
<div class="mb-3 row">
<label for="manager" class="col-sm-1 col-form-label">Manager</label>
<div class="col-sm-3">
<select class="form-control capManager" asp-for="#project.Manager"></select>
</div>
<label for="budgetYear" class="col-sm-2 col-form-label" style="text-align: right">Budget Year</label>
<div class="col-sm-1">
<input type="text" class="form-control" asp-for="#project.BudgetYear">
</div>
<label for="budgetQuarter" class="col-sm-1 col-form-label">Quarter</label>
<div class="col-sm-1">
<input type="text" class="form-control" asp-for="#project.BudgetQuarter">
</div>
<div class="col-sm-3"></div>
</div>
</form>
</div>
</div>
}
Javascript
function populateManagerOptions() {
//Populate Manager options
$.ajax({
url: '/Lookup/GetProjManagerData/',
type: 'GET',
data: {
'reason': 'dropdown'
},
dataType: 'json',
success: function (json) {
const collection = document.getElementsByClassName("capManager");
for (let i = 0; i < collection.length; i++) {
$.each(json, function (i, value) {
collection[i].append($('<option>').text(value.mgrname).attr('value', value.projmgr));
});
}
}
});
}
Controller
[HttpGet]
public IActionResult GetProjManagerData(string reason)
{
try
{
IEnumerable<TblProjmgr> codes = _context.TblProjmgr.AsEnumerable();
if (reason == "dropdown")
return Json(codes);
else
return Json(new { data = codes });
}
catch (Exception ex)
{
_logger.LogError(ex, DateTime.Now + "- Error occured during GetCauseData()");
return Json(new { error = ex.Message.ToString() });
}
}
How do I properly populate the manager select for each form?

I found out the answer to be that I need to create an instance of the dropdown when I create the model data. So for each instance of Model.Projects; each project I defined the full dropdown alongside the selected value.
I use Razor to then define the dropdown as such:
<select class="form-select" asp-for="#project.Manager" asp-items="#project.ManagerList"></select>

Related

Setting Events for similar fields in HTML using JQuery, and Javascript

I am not really good at the HTML world, and I'm not even sure how to debug this one. Anyway, I have an ASP.NET core App. My issue is in a CSHTML view. It is a timeclock system. User logs time against an existing job.
I have an Index.cshtml that is working. It will verify a JobNumber to make sure it exists in the database. And if the user enters a partial number and hits F3, it pops up a modal window (I'm using Bootstrap 5) to allow them to select from a list.
The problem is, the user wants to add more Job numbers. So, they can clock time against up to five Jobs at once. So, I am creating new fields, and naming them JobNumber2, JobNumber3, etc.
What I want to do is reuse the existing scripts to add the verification and popup functionality to each of the new fields.
I have tried several different things based on a half a dozen tutorials out there, but I am just not good enough at Javascript and JQuery to know how to do this.
Any help is appreciated!
[EDIT]
Ruikai Feng's answer shows how to match the first function, but that one calls validateJobNumber(jobNumber), and the result will update a field -- again based on the same pattern. So, now it updates: jobNumberValidationMessage -- but I need it to update the correct jobNumberValidationMessage depending on which JobNumber field got matched in the first half of this. IDK, maybe these could be combined into one function? I'm not sure. But how do I take what I matched with id^='JobNumber to figure out which jobNumberValidationMessage to update (ie jobNumberValidationMessage2, jobNumberValidationMessage3, etc) ;
------------ END EDIT
Here's the code I have that is working, but needs changed:
#using Microsoft.AspNetCore.Http
#using Microsoft.AspNetCore.Http.Extensions
#model dynamic
<!DOCTYPE html>
<html>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-10">
<!-- Clock-In Header -->
<h3>
<img class="logo large" src="logo-png-transparent.png")"
alt="Logo" width="100" height="100"> Add Job Number(s) to Track Time for: #Model.Employee.Name
</h3>
<hr /> <!-- Ruler Line for Separation -->
<!-- End Clock-In Header -->
<!-- Clock-In Form -->
<div class="row">
<div class="col-1 col-md-12 offset-md-0">
<div class="card">
<div class="card-body">
<form asp-action="ClockInBegin" method="post">
<label for="JobNumber" class="col-7 col-md-2 col-form-label text-md-right">Job Number</label>
<div class="col-md-4">
<input type="text" id="JobNumber" name="JobNumber" class="form-control" onkeydown="jobNumberKeyDown(this)" onblur="jobNumberBlur(this)" value="#Model.TrackingItem.JobNumber">
<div class="col-md-8">
<span id="jobNumberValidationMessage"></span>
</div>
</div>
</div>
<div class="form-group row">
<div class="form-check form-switch col-4 align-with-label">
<input class="form-check-input" type="checkbox" value="" id="MultipleCheck">
<label class="form-check-label" for="MultipleCheck">Multiple</label>
</div>
</div> <!-- End form-group row -->
<div>
<button type="submit" class="btn btn-primary w-100">Start Clock</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Clock-In Modal Pop-up -->
<div class="modal fade" id="myModal">
<div class="modal-dialog modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Select Job Number</h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body">
<select id="jobNumberSelect" class="form-control">
<option value="">Select Job Number</option>
<!-- Dynamic options generated via JavaScript or ajax -->
</select>
</div>
<div class="modal-footer">
<button type="button" id="CANCEL"class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" id="OK" class="btn btn-primary" data-bs-dismiss="modal">OK</button>
</div>
</div>
</div>
<!-- End Clock-In Modal Pop-up -->
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$("#JobNumber").blur(function () {
var jobNumber = $(this).val();
validateJobNumber(jobNumber);
});
$("#JobNumber").keydown(function (event) {
if (event.key === "F3") {
event.preventDefault();
if (event.target.value.length >= 2) {
// Open the modal
$('#myModal').modal('show');
// Populate the select options
$.ajax({
type: "GET",
url: "#Url.Action("GetJobNumbers")",
data: { searchTerm: event.target.value },
dataType: "json",
success: function (data) {
$("#jobNumberSelect").empty();
$.each(data, function (index, item) {
$("#jobNumberSelect").append("<option value='" + item + "'>" + item + "</option>");
});
$("#jobNumberSelect").val("..."); // clear the initial value. Make them select it
//set prompt in first cell of select
$("#jobNumberSelect").prepend("<option value=''>Select Job Number</option>");
$("#myModal").modal("show");
}
});
}
}
});
$("#jobNumberSelect").change(function () {
$("#JobNumber").val($(this).val());
});
$("#OK").click(function () {
$("#JobNumber").val($("#jobNumberSelect").val());
validateJobNumber(); // call the validation
$("#myModal").modal("hide");
});
$('#MultipleCheck').change(function () {
if (this.checked) {
$(this).val(true);
$('[name="MultipleCheck"]:hidden').val(true);
$("#hiddenFields").show();
}
else {
$(this).val(false);
$("#hiddenFields").hide();
}
})
}); // end Document.Ready functions
function validateJobNumber() {
var jobNumber = $("#JobNumber").val();
$.ajax({
type: "POST",
url: "#Url.Action("VerifyJobNumber")",
data: { jobNumber: jobNumber },
dataType: "text",
success: function (respdata) {
// alert(respdata);
const obj = JSON.parse(respdata);
var rmessage = obj.message;
$("#jobNumberValidationMessage").text(rmessage);
$("#jobNumberValidationMessage").css("color", "green");
}
});
}
</script>
</body>
</html>
if you have mutipule inputs like:
<input type="text" id="JobNumber1" name="JobNumber1" class="form-control"  value="1">
<input type="text" id="JobNumber2" name="JobNumber2" class="form-control"  value="2">
<input type="text" id="JobNumber3" name="JobNumber3" class="form-control"  value="3">
and you want validate the value on blur ,just try as below:
$("[id^='JobNumber']").blur(function(e)        
{             
var jobnumber=$(this).val();             
$.ajax({               
 type: "POST",               
 url: "#Url.Action("VerifyJobNumber")",               
 data: { "jobNumber": jobnumber },               
 dataType: "text",                
success: function (respdata) {                     
alert(respdata);                                  
 }            
});        
});
With a controller :
[HttpPost]       
public IActionResult VerifyJobNumber(string jobNumber)        
{            
return Ok(jobNumber);        
}
The result:

jquery not sending data to Post Action Asp.Net Core MVC

I am trying to save a ViewModel object from a partial view in a modal, and I get a 404 error when I try to post it. The url is being called, but the ViewModel data isn't being sent. I have been reading similar questions on here and on MSN for hours and nothing I've tried fixes the problem. I took out the repetitive days of the week code for brevity, but I can
add them back in if anyone wants a complete working example. Here is the code
EmployeeViewModel
public class EmployeeViewModel
{
public bool Monday { get; set; } = false;
//...bool properties for Tuesday through Sunday
public Employee Employee { get; set; }
}
Employee/ _AddEmployeeModalPartial
#model JSarad_C868_Capstone.ViewModels.EmployeeViewModel
#Html.AntiForgeryToken()
<div class="modal modal-fade" id="addEmployee">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="addEmpoyeeLabel">Add Employee</h4>
<button type=button class="close" data-bs-dismiss="modal">
<span>x</span>
</button>
</div>
<div class="modal-body">
<form action="Add">
<div class="form-group">
<input asp-for="Employee.Id" class="form-control" />
<input asp-for="Employee.Availability" class="form-control" />
<label asp-for="Employee.Role"></label>
<select asp-for="Employee.Role" class="form-control">
<option value="Bartender">Bartender</option>
<option value="Server">Server</option>
</select>
<span asp-validation-for="Employee.Role" class="text-danger"></span>
</div>
#*<div class="mb-3">*#
<div class="form-group">
<label asp-for="Employee.Name"></label>
<input asp-for="Employee.Name" class="form-control" />
<span asp-validation-for="Employee.Name" class="text-danger"></span>
</div>
#* <div class="mb-3">*#
<div class="form-group">
<label asp-for="Employee.Phone"></label>
<input asp-for="Employee.Phone" class="form-control" />
<span asp-validation-for="Employee.Phone" class="text-danger">
</span>
</div>
#*<div class="mb-3">*#
<div class="form-group">
<label asp-for="Employee.Email"></label>
<input asp-for="Employee.Email" class="form-control" />
<span asp-validation-for="Employee.Email" class="text-danger">
</span>
</div>
#*<div class="mb-3">*#
<div class="form-group">
<label asp-for="Employee.Address"></label>
<input asp-for="Employee.Address" class="form-control" />
<span asp-validation-for="Employee.Address" class="text-danger">
</span>
</div>
#* <div class="mb-3">*#
<div class="form-group">
<label>Availabiliy</label>
</div>
<div class="row pb-4">
<div class="col">
<div class="form-check">
<input asp-for="Monday" class="form-check-input"
type="checkbox" />
<label asp-for="Monday" class="form-check-label"></label>
</div>
<!--...//form check boxes for Tuesday trough Sunday -->
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary"
data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary"
data-bs-save="modal">Save</button>
</div>
</div>
</div>
</div>
EmployeeController.cs
[HttpGet]
public IActionResult Add()
{
EmployeeViewModel viewModel = new EmployeeViewModel();
return PartialView("_AddEmployeeModalPartial", viewModel); ;
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Add(EmployeeViewModel viewModel) //code never reaches this Action
{
viewModel.Employee.Availability = ConvertDaysToChar(viewModel.Employee.Availability)
if (ModelState.IsValid)
{
_db.Employees.Add(viewModel.Employee);
_db.SaveChanges();
return RedirectToAction("Index");
}
else
{
return PartialView("_AddEmployeeModelPartial", viewModel);
}
}
site.js
$(function () {
var PlaceHolderElement = $('#PlaceHolderHere');
$('button[data-bs-toggle="ajax-modal"]').click(function (event) {
/* event.preventDefault();*/
var url = $(this).data('url');
console.log(url)
$.get(url).done(function (data) {
PlaceHolderElement.html(data);
PlaceHolderElement.find('.modal').modal('show');
})
})
PlaceHolderElement.on('click', '[data-bs-save="modal"]', function (event) {
event.preventDefault();
var form = $(this).parents('.modal').find('form');
var actionUrl = form.attr('action');
console.log(actionUrl);
var sendViewModel = form.serialize();
console.log(sendViewModel);
//$.post(actionUrl, sendViewModel).done(function (data) {
// PlaceHolderElement.find('.modal').modal('hide');
/*above is the code from a tutorial for modals. It also doesn't send the object to
post action*/
$.ajax({
type: 'POST',
url: actionUrl,
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify(sendViewModel),
success: function (result) {
console.log('Data received: ');
console.log(result);
}
})
})
})
When I click the save button on the model, the console.log(sendViewModel) returns the correct Serialization with all of the properties and their correct names. And the properties change correctly when there is input.
Employee.Id=&Employee.Availability=&Employee.Role=Bartender&Employee.Name=&Employee.Phone=&Employee.Email=&Employee.Address=&Monday=false&Tuesday=false&Wednesday=false&Thursday=false&Friday=false&Saturday=false&Sunday=false
But I get an error "Failed to load resource: the server responded with a status of 404 ()"
and when I check it the page says "No webpage was found for the web address: https://localhost:44313/Add HTTP ERROR 404" as if it's trying to get a post. It is also missing the controller, but if I change my form action to "Employee/Add" in the _Partial view it still doesn't send the data along with the url, which is causing an entirely different problem. I would greatly appreciate any help or guess or input of any kind. I'm about five seconds away from throwing my laptop out the window on this one. Thanks.
1.Remove the #Html.AntiForgeryToken() inside your form,like below:
<form action="Add" >
#Html.AntiForgeryToken()
....
Then after you serialize the form you can get the AntiForgeryToken, like below:
Because when you don't add #Html.AntiForgeryToken()inside form, after you serialize the form you don't get the AntiForgeryToken, like below:
Besides, if you use <form asp-action="Add" > In ASP.Net Core anti forgery token is automatically added to forms, so you don't need to add #Html.AntiForgeryToken(),you can find in the below :
2.change your ajax like below:
$.ajax({
type: 'POST',
url:'/Employee/Add',
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
data: sendViewModel,
success: function (result) {
console.log('Data received: ');
console.log(result);
}
})
result:
First, I had to change the form action from "Add" to "Employee/Add". ThenI had to remove the antiforgery token from my post action. The first code that is commented out actually works fine otherwise. In my defense I did remove the antiforgery token when I had the wrong URL, but I forgot to retest that when I had the correct one.

RedirectToAction in Loop process [.Net Core 3.1]

I've been struggling to finish the app I'm developing,
here is the scenario:
I have a Razor page where the user will input customer number, Company Code, and Date. Users can input multiple customer numbers and the app will split them by comma.
once the user inputted the details a button with asp-action pointed to the action named GenerateSoa, it will run a foreach statement that will RedirectToAction for every customer that is inputted on the GUI
The problem starts here when the loop runs it only opens one tab even if there are 3 customers inputted.
It should open 3 tabs with their details for 3 different customers. below is my code
I did not however include the SoaLooper cshtml file.
SoaController.cs
public IActionResult GenerateSoa()
{
ClearAmounts();
#region Date management for SOA
// First day of Current Month
var FirstDateOfCurrentMonth = new DateTime(SD.DateToday.Year, SD.DateToday.Month, 1);
var PreviousMonthFirstDay = FirstDateOfCurrentMonth.AddMonths(-1);
var PreviousMonthLastDay = DateTime.DaysInMonth(SD.DateToday.Year, PreviousMonthFirstDay.Month);
****** Ommitted some code *****
// Get last day of Previews month
var PreviewsBalanceDate = PreviousMonthFirstDay.Month.ToString() + "/" +
PreviousMonthLastDay.ToString() + "/" + PreviousMonthFirstDay.Year.ToString();
#endregion Date management for SOA
//SD.GuiCustomerNum = customer.ToString();
var bsid_unpaid_payments = _context.BSIDs.Where(l =>
(l.UMSKZ == "" || l.UMSKZ != "C") && l.BLART == "DJ");
foreach (var payments in bsid_unpaid_payments)
{
SD.PAmount += Convert.ToDouble(payments.DMBTR);
}
SD.UPTotalAmount = SD.UPAmount - SD.PAmount;
return View();
}
public IActionResult SoaLooper(string customer, int company, DateTime asof)
{
string[] customerNum = customer.Split(',');
SD.GuiCompany = company.ToString();
SD.DateToday = asof;
foreach (var item in customerNum)
{
SD.GuiCustomerNumSelected = item.ToString();
RedirectToAction(nameof(GenerateSoa));
}
return View();
}
Index.cshtml
<div class="container h-100">
<div class="row h-100 justify-content-center align-items-center border">
<form method="post" class="col-12 text-center">
<div class="col-12 border-bottom">
<h2 class="text-primary">Statement of Account</h2>
</div>
<div class="col-8 pt-4">
<div class="form-group row">
<div class="col-4">
<label class="float-right">Customer</label>
</div>
<div class="col-8">
<input id="customer" name="customer" class="form-control" />
</div>
</div>
<div class="form-group row">
<div class="col-4">
<label class="float-right">Company Code</label>
</div>
<div class="col-8">
<select id="company" name="company" class="form-control">
<option value="">Select a number</option>
<option value="2000">2000</option>
<option value="3000">3000</option>
</select>
</div>
</div>
<div class="form-group row">
<div class="col-4">
<label class="float-right">Statement as of</label>
</div>
<div class="col-8">
<input id="asof" name="asof" type="date" class="form-control" />
</div>
</div>
<div class="form-group row">
<div class="col-8 offset-4">
<div class="row">
<div class="col">
<button type="submit" formtarget="_blank" id="btnCheck"
class="btn btn-primary form-control" asp-action="SoaLooper">Generate</button>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
RedirectToAction doesn't open a new tab, it just returns a status code of 302 to tell the client to redirect.
If you really want to open multiple new tabs, you should do something like return a list of urls and then use window.open when the page loads.
I haven't tested it but you could do something like this:
Add your url to a list:
SoaController.cs
var newTabUrls = new List<string>();
foreach (var item in customerNum)
{
SD.GuiCustomerNumSelected = item.ToString();
newTabUrls.Add(nameof(GenerateSoa));
}
return View(newTabUrls);
Index.cshtml
<script type="text/javascript">
#if(Model?.Any() ?? false)
{
#foreach(var url in Model)
{
#:window.open(url, "_blank");
}
}
</script>
Open a URL in a new tab (and not a new window)
how to open a page in new tab on button click in asp.net?

Already sucess to add select form dyamically , but the data from success ajax cannot be send to the new select form

I'm trying to make a dependent dropdown, and it already works.
The problem is, the user want the second dropdown (in a different div) to be added dynamically but when we try to add a new dropdown, the new dropdown doesn't show any data when I choose value from first dropdown.
How to make the new dropdown contain data from ajax?
P.S: the option value is in another html where the ajax call the html if it succeeds.
This is the html:
$(document).ready(function() {
$("#dataselect").change(function() {
var urls = "{% url 'polls:load-column' %}";
var column = $(this).val();
$.ajax({
url: urls,
data: {
'column': column
},
success: function(data) {
$("#columnselect").html(data);
},
error: function(data) {
alert("error occured");
}
});
});
});
function appendBox() {
$('#test').append('<select id ="columnselect" style="width:425px;background-color:white;height:30px;font-color:red;text-align-last:center;"></select>')
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="form-group">
<label class="control-label col-md-3">Table Name</label>
<div class="col-md-4">
<div class="input-group bootstrap-timepicker">
<div class="btn-group">
<select id="dataselect" style="width:425px;background-color:white;height:30px;font-color:red;text-align-last:center;">
</select>
</div>
</div>
</div>
</div>
<div class="form-group">
<button class="btn btn-theme" onclick="appendBox()">Add</button>
<label class="control-label col-md-3">Column Name</label>
<div class="col-md-4" id="test">
<div class="input-group bootstrap-timepicker">
<div class="btn-group">
<select id="columnselect" style="width:425px;background-color:white;height:30px;font-color:red;text-align-last:center;">
</select>
</div>
</div>
</div>
</div>

How To pass the modified data from dual listbox to controller?

I have created a form with two listboxes in which it is possible to move the items from one listbox into another.
The view also loads correctly, but I haven't figured out how to send the modified listbox data back to controller.
The view code is the following:
<script>
$(function() {
$(document)
.on("click", "#MoveRight", function() {
$("#SelectLeft :selected").remove().appendTo("#SelectRight");
})
.on("click","#MoveLeft", function() {
$("#SelectRight :selected").remove().appendTo("#SelectLeft");
});
});
#Html.Hidden("RedirectTo", Url.Action("UserManagement", "Admin"));
<h2>User</h2>
<div class="container">
<form role="form">
<div class="container">
<div class="row">
<div class="col-md-5">
<div class="form-group">
<label for="SelectLeft">User Access:</label>
<select class="form-control" id="SelectLeft" multiple="multiple" data-bind="options : ownership, selectedOptions:ownership, optionsText:'FirstName'">
</select>
</div>
</div>
<div class="col-md-2">
<div class="btn-group-vertical">
<input class="btn btn-primary" id="MoveLeft" type="button" value=" << " />
<input class="btn btn-primary" id="MoveRight" type="button" value=" >> " />
</div>
</div>
<div class="col-md-5">
<div class="form-group">
<label for="SelectRight">Owners:</label>
<select class="form-control" multiple="multiple" id="SelectRight" multiple="multiple" data-bind="options : availableOwners, selectedOptions:availableOwners, optionsText:'FirstName'">
</select>
</div>
</div>
</div>
</div>
</form>
</div>
<script>
var data=#(Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model)));
var selectedOwners = #Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(ViewBag.AccessOwners));
var availableOwners = #Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(ViewBag.Owners));
function viewModel() {
this.username=ko.observable(data.Username);
this.password=ko.observable(data.Password);
this.email=ko.observable(data.Email);
this.isActive=ko.observable(data.IsActive);
this.userId = ko.observable(data.UserId);
this.ownership=ko.observableArray(selectedOwners);
this.availableOwners = ko.observableArray(availableOwners);
this.submit = function()
{
$.ajax({
url: '#Url.Action("UserSave", "Admin")',
type: 'POST',
data: ko.toJSON(this),
contentType: 'application/json',
});
window.location.href = url;
return false;
}
this.cancel = function()
{
window.location.href = url;
return false;
}
};
ko.applyBindings(new viewModel());
var url = $("#RedirectTo").val();
I would be very thankful if anyone could suggest the way to pass all the selected options back to controller by populating the data with modified lists when the submit function is executed.
Thanks!
Before form submission save one side items values in an hidden input element. (comma separated values of listbox items.) The value of hidden element is sent to server by submitting the form. In controller you can do the next things.

Categories