I have a dynamic form that I'm needing to submit to my Controller. I'm attempting to do this using an ajax request after building my Javascript Array of Objects.
When I try to send only a string value to the controller, my model is constantly null. However when I'm trying to send my Javascript array, I'm getting a 400 (Bad Request) reponse.
My dynamic form is used to create an overall Ticket. The Ticket is made up of Entries which can be as many as the End-User is needing as they are able to add a new row to the form table.
The inputs for the form: AccountNumber, AccountDescription, DebitAmount, CreditAmount, PostingDescription, PostDate.
The form table:
#model Areas.TicketEntry.Models.FormTicketSubmissionModel
...
<div class="postDate">
<label asp-for="PostDate" class="control-label"></label>
<input id="PostDateInput" autocomplete="off" />
<span asp-validation-for="PostDate" class="text-danger"></span>
</div>
<form action="Create" method="post" class="ticketForm">
<div class="ticketTable">
<table class="table" id="inputTable">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.AccountNumber)
</th>
<th>
#Html.DisplayNameFor(model => model.AccountDescription)
</th>
<th>
#Html.DisplayNameFor(model => model.DebitAmount)
</th>
<th>
#Html.DisplayNameFor(model => model.CreditAmount)
</th>
<th>
#Html.DisplayNameFor(model => model.PostingDescription)
</th>
<th>
<input type="checkbox" id="checkAllCheckBox" class="allRowCheckBox" value="all" />
</th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < 2; i++)
{
<tr>
<td class="tableAccountNumber">
<input id="#($"form{i}AccountInfo")" list="AccountList" class="AccountInfo">
</td>
<td class="tableAccountDescription">
<input id="#($"form{i}AccountDescription")" class="AccountDescription" />
<span asp-validation-for="AccountDescription" class="text-danger"></span>
</td>
<td class="tableDebitAmount">
<input type="text" data-type="currency" id="#($"form{i}DebitAmount")" class="debitAmount" asp-for="DebitAmount" asp-format="{0:C}" value="0.00" />
<span asp-validation-for="DebitAmount" class="text-danger"></span>
</td>
<td class="tableCreditAmount">
<input type="text" data-type="currency" id="#($"form{i}CreditAmount")" class="creditAmount" asp-for="CreditAmount" asp-format="{0:C}" value="0.00" />
<span asp-validation-for="CreditAmount" class="text-danger"></span>
</td>
<td class="tablePostingDescription">
<input type="text" id="#($"form{i}PostingDescription")" class="postDescrip" value="" />
<span asp-validation-for="PostingDescription" class="text-danger"></span>
</td>
<td class="tableSelectBox">
<input type="checkbox" id="#($"form{i}CheckBox")" class="rowCheckBox" value="selected" />
</td>
</tr>
}
</tbody>
</table>
<div class="tableModifyButtons">
<button id="addRow" type="button">Add Row</button>
<button id="deleteRow" type="button">Delete Row</button>
</div>
</div>
<div class="formButtons">
<button id="submitButton" type="button" class="btn btn-primary">Submit Ticket</button>
</div>
</form>
My Javascript is triggered by my #submitButton being clicked. This iterates over the Ids of the #inputTable and adds the row values to and returns an array.
I can print the array of objects to console and all the values are as expected. I'm currently attempting to stringify the array using JSON to pass it to my controller.
My Javascript for submitting the form:
// Function for submitting data to controller
function submitTickets() {
// Iterate through table and generate type array for ticket submission
// - Add to array of tickets
// - using JSON and stringify it
// - Pass to controller with AJAX
let tickets = getTableTickets('inputTable');
let authToken = $('input[name="__RequestVerificationToken"]');
if (!validateTickets(tickets)) {
setWarningMessage('Invalid Ticket Entries detected. Please review your entries and try again.', 'block');
return;
}
let jsonTickets = JSON.stringify({ "tickets": tickets });
// Ajax it to server
// How to send JSON to server?
$.ajax({
url: "/TicketEntry/Tickets/Create",
type: "POST",
contentType: 'application/json; charset=utf-8',
dataType: 'json',
traditional: true,
data: {
__RequestVerificationToken: authToken,
model: jsonTickets
},
success: function (data, textStatus, jqXHR) {
setMessage('SUCCESS: ' + data.Message, 'block');
},
error: function (jqXHR, textStatus, errorThrown) {
setWarningMessage('Error: ' + jqXHR.statusText + ' - ' + textStatus + ' - ' + errorThrown, 'block');
}
});
console.log(jsonTickets);
console.log('ticket input length: ' + tickets.length);
}
JSON.Stringified array output:
{"model":[{"AccountNumber":"0000000","AccountDescription":"TEST ACCOUNT","DebitAmount":"25.00","CreditAmount":"0.00","PostingDescription":"TEST","PostDate":"07/15/2021"},{"AccountNumber":"0000001","AccountDescription":"TEST ACCOUNT 2","DebitAmount":"25.00","CreditAmount":"0.00","PostingDescription":"TEST","PostDate":"07/15/2021"},{"AccountNumber":"0000002","AccountDescription":"TEST ACCOUNT 3","DebitAmount":"0.00","CreditAmount":"50.00","PostingDescription":"TEST","PostDate":"07/15/2021"}]}
My current View Model:
public class FormTicketSubmissionModel
{
[Display(Name = "Account Number")]
public string AccountNumber { get; set; }
[DataType(DataType.Text)]
[StringLength(29, ErrorMessage = "Description is too long!")]
[RegularExpression(#"^[a-zA-Z0-9+&.""/'\s-]*$")]
[Display(Name = "Account Description")]
public string AccountDescription { get; set; }
[Display(Name = "Posting Description")]
[StringLength(29, ErrorMessage = "Posting Description is too long!")]
[RegularExpression(#"^[a-zA-Z0-9+&.""/'\s-]*$")]
public string PostingDescription { get; set; }
[Display(Name = "Post Date")]
[DataType(DataType.Date)]
public DateTime PostDate { get; set; }
[Display(Name = "Debit Amount")]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18,2)")]
[Required]
public decimal DebitAmount { get; set; } = 0.00m;
[Display(Name = "Credit Amount")]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18,2)")]
[Required]
public decimal CreditAmount { get; set; } = 0.00m;
}
I've tried passing only string values using my Ajax, but my model was consistantly null.
Here is my current Action Method:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([FromBody]List<FormTicketSubmissionModel> model)
{
if (ModelState.IsValid)
{
// Validate data within models and save them to database
// ...
return RedirectToAction(nameof(Index));
}
return View(model);
}
How can I pass an Array of Objects from Javascript to my Controller?
Thank you in advance for any help!
After revisiting #Llama 's shared link, I re-designed my model(s) and form. Also, in my View's Form, I had <form action="Create" .../> instead of <form asp-action="Create" .../>. This caused my form's submission to respond with a 400. My solution no longer needs JavaScript/Ajax.
New models:
public class FormTicketSubmissionModel
{
[HiddenInput]
public int Id { get; set; }
// Stores the values of the entries
public FormTicketEntryModel[] TicketEntries { get; set; }
[Display(Name = "Post Date")]
[DataType(DataType.Date)]
public DateTime PostDate { get; set; }
[DataType(DataType.Text)]
[RegularExpression(#"^[a-zA-Z0-9]*$")]
public string UserName { get; set; }
}
public class FormTicketEntryModel
{
[HiddenInput]
public int Id { get; set; }
[Display(Name = "Account Number")]
public string AccountNumber { get; set; }
[DataType(DataType.Text)]
[StringLength(29, ErrorMessage = "Description is too long!")]
[RegularExpression(#"^[a-zA-Z0-9+&.""/'\s-]*$")]
[Display(Name = "Account Description")]
public string AccountDescription { get; set; }
[Display(Name = "Posting Description")]
[StringLength(29, ErrorMessage = "Posting Description is too long!")]
[RegularExpression(#"^[a-zA-Z0-9+&.""/'\s-]*$")]
public string PostingDescription { get; set; }
[Display(Name = "Debit Amount")]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18,2)")]
[Required]
public decimal DebitAmount { get; set; } = 0.00m;
[Display(Name = "Credit Amount")]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18,2)")]
[Required]
public decimal CreditAmount { get; set; } = 0.00m;
}
My new View:
<form asp-action="Create" method="post" class="ticketForm">
<input asp-for="Id" />
<div class="ticketTable">
<table class="table" id="inputTable">
<thead>
<tr>
<th>
<label>Account Number</label>
</th>
<th>
<label>Account Description</label>
</th>
<th>
<label>Debit Amount</label>
</th>
<th>
<label>Credit Amount</label>
</th>
<th>
<label>Posting Description</label>
</th>
<th>
<input type="checkbox" id="checkAllCheckBox" class="allRowCheckBox" value="all" />
</th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < 2; i++)
{
<tr>
<td class="tableAccountNumber">
<input id="#($"form{i}AccountInfo")" asp-for="#Model.TicketEntries[i].AccountNumber" list="AccountList" class="AccountInfo">
</td>
<td class="tableAccountDescription">
<input id="#($"form{i}AccountDescription")" asp-for="#Model.TicketEntries[i].AccountDescription" class="AccountDescription" />
<span asp-validation-for="#Model.TicketEntries[i].AccountDescription" class="text-danger"></span>
</td>
<td class="tableDebitAmount">
<input type="text" data-type="currency" id="#($"form{i}DebitAmount")" class="debitAmount" asp-for="#Model.TicketEntries[i].DebitAmount" asp-format="{0:C}" value="0.00" />
<span asp-validation-for="#Model.TicketEntries[i].DebitAmount" class="text-danger"></span>
</td>
<td class="tableCreditAmount">
<input type="text" data-type="currency" id="#($"form{i}CreditAmount")" class="creditAmount" asp-for="#Model.TicketEntries[i].CreditAmount" asp-format="{0:C}" value="0.00" />
<span asp-validation-for="#Model.TicketEntries[i].CreditAmount" class="text-danger"></span>
</td>
<td class="tablePostingDescription">
<input type="text" id="#($"form{i}PostingDescription")" asp-for="#Model.TicketEntries[i].PostingDescription" class="postDescrip" value="" />
<span asp-validation-for="#Model.TicketEntries[i].PostingDescription" class="text-danger"></span>
</td>
<td class="tableSelectBox">
<input type="checkbox" id="#($"form{i}CheckBox")" class="rowCheckBox" value="selected" />
</td>
</tr>
}
</tbody>
</table>
<div class="tableModifyButtons">
<button id="addRow" type="button">Add Row</button>
<button id="deleteRow" type="button">Delete Row</button>
</div>
</div>
<div class="formButtons">
<button id="submitButton" type="submit" class="btn btn-primary">Submit Ticket</button>
</div>
</form>
Related
When I run the page, and click on the value in the partial table nothing happens with the onclick event. the values are not populating on the textboxes.I set the style of the anchor element to cursor: pointer. Debugging the code as shown in the images, the values populate correctly they just do not appear in the textboxes.
index.cshtml
#page "{id?}"
#model IndexModel
#{ViewData["Title"] = "Test";}
<div class="container">
<div class="row">
<div class="text-center">
<h1 class="display-4">#Model.PageTitle</h1>
</div>
</div>
<div class="row">
<form class="mt-0" method="get">
<div class="row">
<div class="col-3 offset-1" id="ApplicationResult">
</div>
<div class="col-4" id="ApplicationOwnerResult">
</div>
<div class="col-3" id="ApplicationDmvResult">
</div>
</div>
</form>
</div>
<div class="row">
<form class="mt-0" method="post">
<div class="row">
<label class="col-2 offset-4 col-form-label">Date of Birth:</label>
<div class="col-2">
<input class="form-control" title="Date of birth" oninput="validate()" asp-for="DateOfBirth">
<span asp-validation-for="DateOfBirth"></span>
</div>
</div>
<br>
<div class="row">
<label class="col-2 offset-4 col-form-label">Driver's License Number:</label>
<div class="col-2">
<input class="form-control" title="Driver's license number" oninput="validate()" asp-for="DriversLicenseNumber">
<span asp-validation-for="DriversLicenseNumber"></span>
</div>
</div>
<br>
<div class="row">
<button class="btn btn-outline-dark col-1 offset-5" type="submit" id="Submit" disabled asp-page-handler="Submit">Submit</button>
<button class="btn btn-outline-dark col-1" type="button" id="Reset" onclick="clearAll()">Reset</button>
</div>
<br>
</form>
</div>
</div>
#section Scripts {
<script>
// Any exemption applications found will be displayed when the page initially loads. On POST request GET form will be hidden
$(document).ready(function () {
if ("#Model.Exist" == "DivIsVisible") {
$.ajax({
url: "Index/?handler=Display",
type: "GET",
data: { value: #Model.Id },
headers: { RequestVerificationToken: $('input:hidden[name="__RequestVerificationToken"]').val() },
success: function (data) { $("#ApplicationResult").html(data); }
});
}
else {
$("#ApplicationResult").hide();
}
});
// autofill the inputs
function displayOwnerInfo(id) {
$.ajax({
url: "Index/?handler=DisplayOwnerInfo&value=" + id,
type: "GET",
success: function (data) { $("#DateOfBirth").val(data.DateOfBirth); $("#DriversLicenseNumber").val(data.DriversLicenseNumber); }
});
}
</script>
}
index.cshtml.cs
using DMVServiceReference;
using DMV.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Net.Http;
using System.Runtime.Serialization;
using System.Threading.Tasks;
namespace DMV.Pages
{
public class IndexModel : PageModel
{
public Assess50Context _context;
// Id property refers to checking the PropertyId value for the URL
[BindProperty(SupportsGet = true)] public int Id { get; set; }
// Exist property refers to checking if GetDivs exist on POST request
[BindProperty] public string PageTitle { get; set; } = "Residency Check";
public ResidencyCheckCriteria CheckCriteria { get; set; }
[BindProperty, DataMember, MaxLength(8, ErrorMessage = " "), MinLength(8, ErrorMessage = " "), RegularExpression(#"^([0-9]{8}$)", ErrorMessage = " "), Required(ErrorMessage = " ")] public string DateOfBirth { get => CheckCriteria.DateOfBirth; set => CheckCriteria.DateOfBirth = value; }
[BindProperty, DataMember, MaxLength(13, ErrorMessage = " "), MinLength(13, ErrorMessage = " "), RegularExpression(#"^([A-Za-z0-9]{13}$)", ErrorMessage = " "), Required(ErrorMessage = " ")] public string DriversLicenseNumber { get => CheckCriteria.DriverLicenseNumber; set => CheckCriteria.DriverLicenseNumber = value; }
[BindProperty(SupportsGet = true)] public string Exist { get; set; } = "DivIsVisible";
public IndexModel(Assess50Context context)
{
_context = context;
CheckCriteria = new ResidencyCheckCriteria();
}
// Reads all exemption application table information by property id
public PartialViewResult OnGetDisplay(int value) => Partial("_DisplayApplicationPartial", _context.ExemptionApplications.Where(x => x.PropertyId == value).ToList());
// Reads all exemption application owner information by exemption application id
public PartialViewResult OnGetDisplayOwner(int value) => Partial("_DisplayOwnerPartial", _context.ExemptionApplicationOwners.Where(x => x.ExemptionApplicationId == value).GroupBy(x => x.ExemptionApplicationOwnerId).Select(x => x.First()).ToList());
// Reads the dmv information by application owner ID
// public PartialViewResult OnGetDisplayOwnerInfo(int value) => Partial("_DisplayDMVPartial", _context.ExemptionApplicationDmvinformations.Where(x => x.ExemptionApplicationOwnerId == value).ToList());
public JsonResult OnGetDisplayOwnerInfo(int value)
{
ExemptionApplicationDmvinformation data = _context.ExemptionApplicationDmvinformations.Where(x => x.ExemptionApplicationOwnerId == value).First();
return new JsonResult(new { DateOfBirth = data.DmvDob.ToString(), DriversLicenseNumber = data.DriverLicense });
}
DbContext.cs
using Microsoft.EntityFrameworkCore;
namespace DMV.Models
{
public partial class Assess50Context : DbContext
{
public virtual DbSet<ExemptionApplication> ExemptionApplications { get; set; } = null!;
public virtual DbSet<ExemptionApplicationDmvinformation> ExemptionApplicationDmvinformations { get; set; } = null!;
public virtual DbSet<ExemptionApplicationOwner> ExemptionApplicationOwners { get; set; } = null!;
public Assess50Context() {}
public Assess50Context(DbContextOptions<Assess50Context> options) : base(options) {}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}
}
Application.cs model
using System;
using System.ComponentModel.DataAnnotations;
namespace DMV.Models
{
public partial class ExemptionApplication
{
public int PropertyId { get; set; }
[Display(Name = "Year")] public short YearId { get; set; }
[Display(Name = "App ID")] public int ExemptionApplicationId { get; set; }
[Display(Name = "Reference Number")] public string? ApplicationReference { get; set; }
}
}
Owner.cs model
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace DMV.Models
{
public partial class ExemptionApplicationOwner
{
public int PropertyId { get; set; }
public int ExemptionApplicationId { get; set; }
[Display(Name = "Application Owner ID")] public int ExemptionApplicationOwnerId { get; set; }
[Display(Name = "Owner ID")] public int? OwnerId { get; set; }
public string? FirstName { get; set; }
public string? LastName { get; set; }
[Display(Name = "Name")]public string? AssessProName { get; set; }
}
}
DmvInformation.cs model
using SoapCore.ServiceModel;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace DMV.Models
{
public partial class ExemptionApplicationDmvinformation
{
public int PropertyId { get; set; }
public int ExemptionApplicationId { get; set; }
public int ExemptionApplicationOwnerId { get; set; }
[Display(Name = "DOB")] public DateTime? DmvDob { get; set; }
[Display(Name = "Driver's License #")] public string? DriverLicense { get; set; }
}
}
_DisplayApplicationPartial.cshtml
#model IEnumerable<Models.ExemptionApplication>
#if (Model.Count() != 0)
{
<div id="ExemptionApplicationNav">
<table class="PartialTable">
<thead>
<tr>
<th class="PartialTableRowData" colspan="3">Exemption Applications</th>
</tr>
</thead>
<tbody>
<tr>
<td class="PartialTableRowCategoryData">#Html.DisplayNameFor(m => m.YearId)</td>
<td class="PartialTableRowCategoryData">#Html.DisplayNameFor(m => m.ApplicationReference)</td>
<td class="PartialTableRowCategoryData">#Html.DisplayNameFor(m => m.ExemptionApplicationId)</td>
</tr>
#foreach (Models.ExemptionApplication item in Model)
{
<tr>
<td class="PartialTableRowData">#item.YearId</td>
<td class="PartialTableRowData">#item.ApplicationReference</td>
<td class="PartialTableRowData">
<a class="DMVLabelsTexts" href="Index/?handler=DisplayOwner&value=#item.ExemptionApplicationId">#item.ExemptionApplicationId</a>
</td>
</tr>
}
</tbody>
</table>
</div>
}
else
{
<p>No exemption applications found for this Property ID</p>
}
<script>
$('#ExemptionApplicationNav a').click(function (e) {
$('#ApplicationOwnerResult').hide().load($(this).attr('href'), function () {
$('#ApplicationOwnerResult').show()
})
return false
})
</script>
_DisplayOwnerPartial.cshtml
#model IEnumerable<Models.ExemptionApplicationOwner>
#if (Model.Count() != 0)
{
<div id="OwnerNav">
<table class="PartialTable">
<thead>
<tr>
<th class="PartialTableRowData" colspan="3">Owner Information</th>
</tr>
</thead>
<tbody>
<tr>
<td class="PartialTableRowCategoryData">#Html.DisplayNameFor(m => m.ExemptionApplicationOwnerId)</td>
<td class="PartialTableRowCategoryData" colspan="2">#Html.DisplayNameFor(m => m.AssessProName)</td>
</tr>
#foreach (Models.ExemptionApplicationOwner item in Model)
{
<tr>
<td class="PartialTableRowData">
<a class="DMVLabelsTexts" onclick="displayOwnerInfo('#item.ExemptionApplicationOwnerId')">#item.ExemptionApplicationOwnerId</a>
<!-- <a class="DMVLabelsTexts" href="Index/?handler=DisplayOwnerInfo&value=#item.ExemptionApplicationOwnerId">#item.ExemptionApplicationOwnerId</a> -->
</td>
<td class="PartialTableRowMultipleData">#item.FirstName</td>
<td class="PartialTableRowMultipleData">#item.LastName</td>
</tr>
}
</tbody>
</table>
</div>
}
else
{
<p>No owner data available</p>
}
<!--
<script>
$('#OwnerNav a').click(function (e) {
$('#ApplicationDmvResult').hide().load($(this).attr('href'), function () {
$('#ApplicationDmvResult').show()
})
return false
})
</script>
-->
_DisplayDMVPartial.cshtml
#model IEnumerable<Models.ExemptionApplicationDmvinformation>
#if (Model.Count() != 0)
{
<div id="DmvNav">
<table style=" border: 1px solid black;">
<thead>
<tr>
<th colspan="2" style="border: 1px solid black; text-align: center;">DMV Information</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border: 1px solid black; font-weight: bold; text-align: center;">#Html.DisplayNameFor(m => m.DmvDob)</td>
<td style="border: 1px solid black; font-weight: bold; text-align: center;">#Html.DisplayNameFor(m => m.DriverLicense)</td>
</tr>
#foreach (Models.ExemptionApplicationDmvinformation item in Model)
{
<tr>
<!-- <td style="border: 1px solid black; text-align: center;">item.DmvDob.Value.ToString("MMddyyyy")</td> -->
<td style="border: 1px solid black; text-align: center;">#item.DmvDob</td>
<td style="border: 1px solid black; text-align: center;">#item.DriverLicense</td>
</tr>
}
</tbody>
</table>
</div>
}
else
{
<p>No owner data available</p>
}
Try to change your ajax in the Index.cshtml like below:
// autofill the inputs
function displayOwnerInfo(id) {
$.ajax({
url: "Index/?handler=DisplayOwnerInfo&value=" + id,
type: "GET",
success: function (data) {
$("#DateOfBirth").val(data.dateOfBirth);
$("#DriversLicenseNumber").val(data.driversLicenseNumber);
}
resut:
Scripts in Partials which are themselves loaded by script will not execute. You should place the code that adds the click event handler to the #OwnerNav a element(s) to Index.cshtml. However, you need to use the on method and apply it to an element that exists when the page is initially rendered (e.g. 'body'), passing in the target selector after the name of the event handler:
$('body').on('click', '#OwnerNav a', function (e) {
//
I am using .NET CORE MVC for making some forms for the user to add people to a system (A manual process). One of the forms I've got is a simple multi-add user form that allows the user to enter names on the form and click submit, where it is then serialized and converted into a PDF document to be saved to the local machine.
I wanted to make this with a dynamic HTML Table in mind so I've got the following setup. The intent here is to allow a table to start initially with a single empty, editable row and give the ability to add rows as they need, while binding each row to a list of objects on the model.
User class
[Serializable]
public class User
{
[Display(Name = "M.I.")]
public string MiddleInitial { get; set; }
[Display(Name = "Suffix")]
public string NameSuffix { get; set; }
[Required(AllowEmptyStrings = false)]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required(AllowEmptyStrings = false)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
}
MultiAddUser class
[Serializable]
public class MultiAddUser
{
[Required]
[Display(Name = "Start Date")]
public DateTime StartDate { get; set; }
public List<User> Users { get; set; }
public MultiAddUser()
{
Users = new List<User>();
}
}
My view has the following code that displays the basic table with inputs in the cells with the ability to add cells on the fly.
#using Contract
#model MultiAddUser
#section Scripts{
<script>
function addRow() {
var table = document.getElementById("MultiAddUserTable");
var row = table.insertRow(-1);
var cell1 = row.insertCell(0);
cell1.innerHTML = '<input type="text" />';
var cell2 = row.insertCell(1);
cell2.innerHTML = '<input type="text" />';
var cell3 = row.insertCell(2);
cell3.innerHTML = '<input type="text" />';
var cell4 = row.insertCell(3);
cell4.innerHTML = '<input type="text" />';
}
</script>
}
<style>
input {
width: 100%;
}
</style>
<body>
<h2 class="formtitle">ADD MULTIPLE USERS</h2>
<form method="post" asp-action="AddMultipleUsers" id="addMultiUsers">
<div class="form-group">
<div class="form-row">
<div class="form-group col-sm-2">
<label asp-for="StartDate"></label>
<input type="date" asp-for="StartDate" class="form-control" />
<span asp-validation-for="StartDate" class="text-danger"></span>
</div>
</div>
<table id="AddMultipleUsersTable">
<tr>
<th>First Name</th>
<th>Middle Initial</th>
<th>Last Name</th>
<th>Suffix</th>
</tr>
<tr>
<td><input type="text" /></td>
<td><input type="text" /></td>
<td><input type="text" /></td>
<td><input type="text" /></td>
</tr>
</table>
<button type="button" onclick="addRow()">Add</button>
<hr />
<div class="form-row">
<div id="submitbutton">
<input id="submit" class="btn btn-primary btn-lg" style="background-color: #4CAF50; color:white;" type="submit" />
</div>
</form>
</body>
Now normally with ASP.NET Core MVC you would just have something like asp-for="#Model.Property[IndexIfNeeded]" in the input tag helper but since the list starts empty and is not bound by a database, I'm having trouble piecing together how I would go about adding each new row as a new item to the list on the model once the entire form is submitted.
I may be over complicating this since the data never needs to be entered into a database, but it does need to be serialized and converted into a PDF document and be printed at the end of the process so any insight as to alternative methods to accomplish that would be appreciated.
In summary, How can I bind the rows / columns added dynamically to this table to my model objects, while maintaining validation rules on each required property?
Since your data is not associated with the database, I recommend that you create public variables to store the added and new added data.
And the 'td' tag in view does not support the 'asp-for' attribute, so you can add the input box in 'td' to add new data.
public class HomeController : Controller
{
public static MultiAddUser multiAddUser = new MultiAddUser { };
public static List<User> users = new List<User> { };
public IActionResult Index()
{
ViewBag.UserList = multiAddUser.Users;
return View();
}
public IActionResult Add(User user)
{
if (!ModelState.IsValid)
{
ViewBag.UserList = multiAddUser.Users;
return View("Index");
}
users.Add(user);
multiAddUser.Users = users;
return RedirectToAction("Index");
}
}
Index.cshtml:
#model WebApplication_core.Models.User
#{
ViewData["Title"] = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Index</h1>
<form asp-controller="Home" asp-action="Add">
<table id="MultiAddUserTable" class="table">
<tr>
<th>First Name</th>
<th>Middle Initial</th>
<th>Last Name</th>
<th>Suffix</th>
</tr>
#foreach (var item in (IEnumerable<WebApplication_core.Models.User>)ViewBag.UserList)
{
<tr>
<td>#item.FirstName</td>
<td>#item.MiddleInitial</td>
<td>#item.LastName</td>
<td>#item.NameSuffix</td>
</tr>
}
<tr>
<td contenteditable="true">
<input id="Text1" type="text" asp-for="#Model.FirstName" />
<br /><span asp-validation-for="#Model.FirstName" class="text-danger"></span>
</td>
<td contenteditable="true">
<input id="Text2" type="text" asp-for="#Model.MiddleInitial" />
<br /><span asp-validation-for="#Model.MiddleInitial" class="text-danger"></span>
</td>
<td contenteditable="true">
<input id="Text3" type="text" asp-for="#Model.LastName" />
<br /> <span asp-validation-for="#Model.LastName" class="text-danger"></span>
</td>
<td contenteditable="true">
<input id="Text4" type="text" asp-for="#Model.NameSuffix" />
<br /> <span asp-validation-for="#Model.NameSuffix class="text-danger"></span>
</td>
</tr>
</table>
<input id="Button1" type="submit" value="Add" />
</form>
Here is the result :
Update(2020/3/5) :
public class HomeController: Controller
{
public static List<User> users = new List<User> { new User { } };
public static MultiAddUser multiAddUser = new MultiAddUser
{
Users = users
};
public IActionResult Index()
{
ViewBag.UserList = multiAddUser.Users;
return View();
}
public IActionResult Add(List<User> userLists)
{
if (!ModelState.IsValid)
{
ViewBag.UserList = multiAddUser.Users;
return View("Index");
}
users = userLists;
users.Add(new User { });
multiAddUser.Users = users;
return RedirectToAction("Index");
}
}
Index.cshtml:
#model IList<WebApplication_core.Models.User>
#{
ViewData["Title"] = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
var Model = (IList<WebApplication_core.Models.User>)ViewBag.UserList;
}
<h1>Index</h1>
<form asp-controller="Home" asp-action="Add">
<table id="MultiAddUserTable" class="table">
<tr>
<th>First Name</th>
<th>Middle Initial</th>
<th>Last Name</th>
<th>Suffix</th>
</tr>
#for (int i = 0; i < Model.Count(); i++)
{
<tr>
<td>
<input id="Text1" type="text" asp-for="#Model[i].FirstName" />
<br /><span asp-validation-for="#Model[i].FirstName" class="text-danger"></span>
</td>
<td>
<input id="Text2" type="text" asp-for="#Model[i].MiddleInitial" />
<br /><span asp-validation-for="#Model[i].MiddleInitial" class="text-danger"></span>
</td>
<td>
<input id="Text3" type="text" asp-for="#Model[i].LastName" />
<br /> <span asp-validation-for="#Model[i].LastName" class="text-danger"></span>
</td>
<td>
<input id="Text4" type="text" asp-for="#Model[i].NameSuffix" />
<br /> <span asp-validation-for="#Model[i].NameSuffix" class="text-danger"></span>
</td>
</tr>
}
</table>
<input id="Button1" type="submit" value="Add" />
</form>
Here is the new result :
I want to get the value only on form submit in angular. This is the Code
In my Typescript:
constructor(public navCtrl: NavController, public navParams: NavParams, public modalCtrl: ModalController, public formBuilder: FormBuilder, public alertCtrl: AlertController,
public loadingCtrl: LoadingController) {
this.memleticsForm = formBuilder.group({
changeType: [{}, Validators.required]
});
}
memleticsSubmitForm(form) {
console.log(form);
}
Html:
<form name="learningtestForm" [formGroup]="memleticsForm" (submit)="memleticsSubmitForm(memleticsForm.value)" novalidate>
<table>
<tr>
<th>Question</th>
<th>0</th>
<th>1</th>
<th>2</th>
</tr>
<tr>
<td>You have a personal or private interest or hobby that you like to do alone.</td>
<td>
<input type="radio" formControlName="changeType" [value]=0>
</td>
<td>
<input type="radio" formControlName="changeType" [value]=1>
</td>
<td>
<input type="radio" formControlName="changeType" [value]=2>
</td>
</tr>
</table>
<button ion-button block color="secondary" end type="submit">Submit</button>
When I clicked a button and submits it, the output on my console.log is "Object {changeType: 2}"
But I want to get only the "2" and use it to compute a value like
memleticsSubmitForm(form) {
var x = form * 5;
console.log(x); // if 2 is clicked it should display 10
}
In this case, you could do something like:
memleticsSubmitForm(form) {
console.log(form.changeType);
const changeType = form.changeType; // Your form has this attribute
var x = changeType * 5; // So use it ;)
console.log(x);
}
Hope it helps!!
I am having a main view and few partial views.
The main view is something which displays the list of registered users like this :
The main view code :
#model WebApplication9.Models.User
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<link ref="~/Styles/UserManagement.css" rel="stylesheet" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body>
<p>
<button type="submit" name="btnDefineTraj" onclick="AddUserBtnClick()" id="button1">Create New User</button>
</p>
<div hidden id="divAddUser" title="Add new user" style="border-radius: 7px">
#Html.Partial("~/Views/UserManagement/CreateUser.cshtml")
</div>
<div hidden id="divEditUser" title="Edit user" style="border-radius: 7px">
#Html.Partial("~/Views/UserManagement/EditUser.cshtml", Model)
</div>
<table>
<tr>
<th>UserID
</th>
<th>Username
</th>
<th>Password
</th>
<th>FirstName
</th>
<th>LastName
</th>
<th>DisplayName
</th>
<th>Email
</th>
<th>Pref. Language
</th>
<th>CreatedBy
</th>
<th>CreatedTime
</th>
<th>ModifiedTime
</th>
<th>IsAdmin
</th>
<th>IsActive
</th>
<th></th>
</tr>
#foreach (var item in Model.usersList)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.userId)
</td>
<td>
#Html.DisplayFor(modelItem => item.userName)
</td>
<td>
#Html.DisplayFor(modelItem => item.password)
</td>
<td>
#Html.DisplayFor(modelItem => item.firstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.lastName)
</td>
<td>
#Html.DisplayFor(modelItem => item.displayName)
</td>
<td>
#Html.DisplayFor(modelItem => item.email)
</td>
<td>
#Html.DisplayFor(modelItem => item.languagePreference)
</td>
<td>
#Html.DisplayFor(modelItem => item.createdBy)
</td>
<td>
#Html.DisplayFor(modelItem => item.createdTime)
</td>
<td>
#Html.DisplayFor(modelItem => item.modifiedTime)
</td>
<td>
#Html.DisplayFor(modelItem => item.isAdmin)
</td>
<td>
#Html.DisplayFor(modelItem => item.isActive)
</td>
<td>
<button type="submit" name="btnEditUser" onclick="EditUserBtnClick(#item.userId)" id="buttonEdit">
<img src="~/Images/edit-icon.png" width="20" height="20" />
</button>
</td>
<td>
<button type="submit" name="btnDeleteUser" onclick="DeleteUserBtnClick(#item.userId)" id="buttonDelete">
<img src="~/Images/delete-icon.png" width="20" height="20" /></button>
#* #Html.ActionLink("Edit", "EditUser", new { id=item.userId } ) |
#Html.ActionLink("Delete", "DeleteUser", new { id=item.userId })*#
</td>
</tr>
}
</table>
</body>
</html>
My model class User code is :
public class User
{
public int UserId { get; set; }
public string userName { get; set; }
public string passWord { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
public string displayName { get; set; }
public string emailID { get; set; }
public string languagePreference { get; set; }
public bool isAdministrator { get; set; }
public bool isActive { get; set; }
public IEnumerable<usermaster> usersList{ get; set; }
public usermaster EditUserData { get; set; }
}
As you can see, the table is loaded from usersList in the model.
Now I am trying to implement the edit user functionality. When user clicks on edit button I am opening a partial view :
<div hidden id="divEditUser" title="Edit user" style="border-radius: 7px">
#Html.Partial("~/Views/UserManagement/EditUser.cshtml", Model)
</div>
by passing the id to the controller and getting back the user data so that it can be displayed in the new partial view
function EditUserBtnClick(userid) {
$.ajax({
type: "POST",
url: "/UserManagement/EditUser",
data: JSON.stringify({ userID: userid }),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (edituserDataObj) {
if (msg != null) {
$("#divEditUser").dialog({ width: 350 });
}
else {
$('#lblResult').val("Failed to delete user.");
}
},
error: function () {
return "error";
}
});
I am getting the edituserDataObj properly here. But I am not sure how to pass it to the partial view EditUser.cshtml. I tried to edit the model by adding the new edit user data to a model class property public usermaster EditUserData { get; set; }. But when I access this from my partial view, the data is null.
[HttpPost]
public JsonResult EditUser(int userID)
{
var user = DBManager.Instance.GetUserData(userID);
return Json(user);
}
Is there any way to pass the edit user data to the partial view?
can somebody help me..
this is my Code:
Index.cshtml
<!DOCTYPE html>
<html>
<head>
<title>jQuery With Example</title>
#Scripts.Render("~/bundles/jquery")
<script type="text/javascript">
$(function () {
$('.chkview').change(function () {
$(this).closest('tr').find('.chkitem').prop('checked', this.checked);
});
$(".chkitem").change(function () {
var $tr = $(this).closest('tr'), $items = $tr.find('.chkitem');
$tr.find('.chkview').prop('checked', $items.filter(':checked').length == $items.length);
});
});
function Save() {
$.ajax({
url: #Url.Action("Index", "Home" , "Index"),
type: "POST",
data: formData ,
dataType: "json",
success: function(data){
alert(data.RoleID)
},
error: function(e){
debugger;
}
}
</script>
</head>
<body>
<h2>Access Control-Home</h2>
<br />
#using (Html.BeginForm("Index", "Home", FormMethod.Post, new { RoleID="RoleID" }))
{
<input type="hidden" name="RoleID" value="1" id="RoleID" />
<table id="mytable">
<tr>
<td>View</td>
<td>Insert</td>
<td>Update</td>
<td>Delete</td>
</tr>
<tr>
<td>Administrator</td>
<td>
<input type="checkbox" class="chkview chkview-1" />
</td>
<td>
<input type="checkbox" class="chkitem chkitem-1" />
</td>
<td>
<input type="checkbox" class="chkitem chkitem-1" />
</td>
<td>
<input type="checkbox" class="chkitem chkitem-1" />
</td>
</tr>
<tr>
<td>Free User</td>
<td>
<input type="checkbox" class="chkview chkview-2" />
</td>
<td>
<input type="checkbox" class="chkitem chkitem-2" />
</td>
<td>
<input type="checkbox" class="chkitem chkitem-2" />
</td>
<td>
<input type="checkbox" class="chkitem chkitem-2" />
</td>
</tr>
</table>
<br />
<button type="submit" class="buttons buttons-style-1" onclick="Save()">Save</button>
}
</body>
</html>
HomeController.cs
[HttpPost]
public ActionResult Index(string RoleID)
{
var _roleID = RoleID;
return View();
}
i want to ask 2 question.
how i can parsing value of list checked checkbox using ajax? i want parsing classname of checkbox which i checked example i need list of array if i checked row administrator, { 'chkinsert-1','chkupdate-2' }
how i can get value collection of array in controller post?
example:
public ActionResult Index(string RoleID, array[] collChecbox) contents of collChecbox = { 'chkinsert-1','chkupdate-2'} in accordance with the user checked of checkbox input.
can somebody help me??
Why don't you use Ajax.BeginForm() this makes so easy to send posted form value.
Also, you should create proper model first.
MODEL
public class UserRole
{
public Administrator Administrator { get; set; }
public FreeUser FreeUser { get; set; }
}
public class Administrator
{
public int Checkbox1 { get; set; }
}
public class FreeUser
{
public int Checkbox1 { get; set; }
}
Do following in View.
#model Model.UserRole
<div id="result"></div>
#using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "result" }))
{
<input type="hidden" name="RoleID" value="1" id="RoleID" />
<table id="mytable">
<tr>
<td>View</td>
<td>Insert</td>
<td>Update</td>
<td>Delete</td>
</tr>
<tr>
<td>Administrator</td>
<td>
#Html.CheckBoxFor(m => m.Administrator.Checkbox1)
</td>
</tr>
<tr>
<td>Free User</td>
<td>
#Html.CheckBoxFor(m => m.FreeUser.Checkbox1)
</td>
</tr>
</table>
<br />
<button type="submit" class="buttons buttons-style-1" onclick="Save()">Save</button>
}
Controller action
[HttpPost]
public ActionResult Index(UserRole model)
{
return View();
}
Also don't forget to include ajax library.
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>