I am simply binding a list of observable objects to a TR inside an html table. When the user selects a row(only one can be selected), i want that selected row or observable object to be removed from the observable array. I have the remove working but it's completely ignoring whether the row is selected or not. I am using a flag on each row to determine whether they are checked or not but the value is always true...even if you uncheck the checkbox on the row which is why it removes them all. Can someone please shed light on the below knockout setup...days of research and testing but KO just hates me :(
<table class="accountGroups" id="tblAccountGroups">
<tr>
<td width="150px;" style="font-weight: bold;">StandardAccountNo</td>
<td width="100px;" style="font-weight: bold;">Primary</td>
<td style="font-weight: bold;">Effective Date</td>
<td style="font-weight: bold;">End Date</td>
</tr>
<!-- ko foreach: NewAccountGroupDetails-->
<tr id="Model.NewAccountGroupDetails[0].AccountGroupName" rowindex="$index()" class="acctgrp-row" data-bind="click: $root.selectedRow">
<td>
<div>
<input type="text" data-bind="value: StandardAccountNo, attr: {name: 'NewAccountGroupDetails[' + $index() + '].StandardAccountNo'}" />
</div>
</td>
<td style="border:2px inset;border-color:gray;">
<div style="text-align:center;">
<input type="radio" data-bind="value: IsPrimary, attr: {name: 'NewAccountGroupDetails[' + $index() + '].IsPrimary'}" />
</div>
</td>
<td>
<div style="width:115px;">
<input type="text" data-bind="value: EffectiveDate, attr: {name: 'NewAccountGroupDetails[' + $index() + '].EffectiveDate'}" readonly="readonly" />
</div>
</td>
<td>
<div style="width:115px;">
<input type="text" data-bind="value: EndDate, attr: {name: 'NewAccountGroupDetails[' + $index() + '].EndDate'}" readonly="readonly" />
</div>
</td>
<td>
<input type="hidden" data-bind="value: ContractType, attr: {name: 'NewAccountGroupDetails[' + $index() + '].ContractType'}" />
<input type="hidden" data-bind="value: CompanyID, attr: {name: 'NewAccountGroupDetails[' + $index() + '].CompanyID'}" />
<input type="hidden" data-bind="value: AccountGroupName, attr: {name: 'NewAccountGroupDetails[' + $index() + '].AccountGroupName'}" />
<input type="checkbox" data-bind="checked: IsSelected, attr: {name: 'NewAccountGroupDetails[' + $index() + '].IsSelected'}" />
</td>
</tr>
<!-- /ko -->
</table>
</div>
</div>
<br />
<div class="row">
<div class="col-lg-2 col-sm-2"> </div>
<div class="col-lg-2 col-sm-2" style="text-align:right;">
<input type="button" value="New" data-bind="click: addNew" />
</div>
<div class="col-lg-2 col-sm-2">
<input type="button" value="Remove" data-bind="click: remove" />
</div>
<div class="col-lg-3 col-sm-2"> </div>
<div class="col-lg-2 col-sm-2">
<input type="button" value="Save" id="btnSave" />
</div>
</div>
JS
$(document).on('ready', function () {
ko.applyBindings(new AccountGroupViewModel());
});
function AccountGroupViewModel() {
var viewModel = this;
//Convert Model property into observable array for KO
var rawList = '#Html.Raw(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model.NewAccountGroupDetails))';
viewModel.NewAccountGroupDetails = ko.observableArray(convertJSONToKoObservableObject($.parseJSON(rawList)));
//Add properties to the vm and an empty ko object to the array
viewModel.NewAccountGroupDetails.push(newAccountGroupDetail());
viewModel.addNew = function () {
viewModel.NewAccountGroupDetails.push(newAccountGroupDetail());
}
viewModel.remove = function (row) {
viewModel.NewAccountGroupDetails.remove(function (item) {
return item.IsSelected();
});
}
}
function convertJSONToKoObservableObject(json) {
var ret = [];
$.each(json, function (i, obj) {
var newOBJ = {};
for (prop in obj) {
newOBJ[prop] = ko.observable(obj[prop]);
}
ret.push(newOBJ);
});
return ret;
}
function newAccountGroupDetail() {
this.StandardAccountNo = ko.observable('');
this.IsPrimary = ko.observable(false);
this.EffectiveDate = ko.observable(new Date());
this.EndDate = ko.observable(new Date());
this.AccountGroupName = ko.observable($('#txtAccountGroupName').val());
this.ContractType = ko.observable($('#ddlContractTypes').val());
this.CompanyID = ko.observable($('#ddlCompany').val());
this.IsSelected = ko.observable(false);
return this;
}
You have couple of mistakes here
viewModel.selectedDetails = ko.computed(function () {
ko.utils.arrayForEach(viewModel.NewAccountGroupDetails(), function (row) {
row.IsSelected(true);
});
});
This piece of code row.IsSelected(true); is actually set IsSelected observable value to true.
To remove item from ObservableArray you should use something like:
viewModel.NewAccountGroupDetails.remove(function(item) {
return item.IsSelected();
});
Also to convert json value to viewModel, take a look at the mapping plugin
Related
I am try to understand what happened with checkbox status. So I have Create Page where I insert Patient
and when I click Emergency to True in Index Page I always get False
IndexPage.cshtml
#if (Model.Count() > 0)
{
<table class="table table-bordered table-striped" style="width:100%">
<thead>
<tr>
<th>
Doctor Full Name - CODE
</th>
<th>
Patient Full Name
</th>
<th>
Date and Time
</th>
<th>
Emergency
</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var obj in Model)
{
<tr>
<td width="25%">#obj.Doctor.Firstname #obj.Doctor.Lastname #obj.Doctor.Code</td>
<td width="25%">#obj.Patient.FirstName #obj.Patient.LastName</td>
<td width="25%">#obj.DateAndTime</td>
<td width="25%" class="blink_me">#obj.Emergency</td>
<td class="text-center">
<div class="w-75 btn-group" role="group">
<a asp-route-Id="#obj.Id" asp-action="Upsert" class="btn btn-primary mx-2">
<i class="fas fa-edit"></i>
</a>
<a asp-route-Id="#obj.Id" asp-action="Delete" class="btn btn-danger mx-2">
<i class="far fa-trash-alt"></i>
</a>
</div>
</td>
</tr>
}
</tbody>
</table>
}
else
{
<p> No Admission Patient exists.</p>
}
Create
#model BergClinics.Models.ViewModel.AdmisionVM
#{
ViewData["Title"] = "Upsert";
var title = "Create Admission Patient";
}
<form method="post" enctype="multipart/form-data">
#if (Model.AdmissionPatient.Id != 0)
{
<input asp-for="AdmissionPatient.Id" hidden />
title = "Edit Admission Patient";
}
<div class="border p-3">
<div class="form-group row">
<h2 class="text-info pl-3">#title</h2>
</div>
<div class="row">
<div class="col-8">
<div class="form-group row py-2">
<div class="col-4">
<label>Doctor Full Name : </label>
</div>
<div class="col-8">
<select asp-for="AdmissionPatient.DoctorId" asp-items="#Model.DoctorSelectList" class="form-control">
<option disabled selected>--Select Docotor--</option>
</select>
</div>
</div>
<div class="form-group row py-2">
<div class="col-4">
<label>Patient Full Name: </label>
</div>
<div class="col-8">
<select asp-for="AdmissionPatient.PatientId" asp-items="#Model.PatientSelectList" class="form-control">
<option disabled selected>--Select Patient--</option>
</select>
</div>
</div>
<div class="form-group row py-2">
<div class="col-4">
<label>Date and Time :</label>
</div>
<div class="col-8">
<input asp-for="AdmissionPatient.DateAndTime" asp-format="{0:dd/MM/yyyy}" type="text" name="date" class="form-control datepicker" autocomplete="off">
</div>
</div>
<div class="form-group row py-2">
<div class="col-4">
<label>Patient Image :</label>
</div>
<div class="col-3">
<input type="file" name="files" id="imageBox" multiple class="form-control" />
</div>
</div>
<div class="form-group row py-2">
<div class="col-4">
<label>Emergency reception :</label>
</div>
<div class="col-8">
<input type="checkbox" class="form-control" id="emergencyId">
<label class="form-check-label" for="exampleCheck1"></label>
</div>
</div>
<div class="form-group row py-2">
<div class="col-8 offset-4 row">
<div class="col">
#if (Model.AdmissionPatient.Id != 0)
{
//update
<input type="submit" class="btn btn-info w-100" value="Update" />
}
else
{
//create
<input type="submit" onclick="return validateInput()" class="btn btn-primary w-100" value="Create" />
}
</div>
</div>
</div>
</div>
<div class="col-4">
#if (Model.AdmissionPatient.Id != 0)
{
<img src="#Constans.imagePath#Model.AdmissionPatient.Image" width="100%" style="border-radius:5px; border:1px solid #bbb" />
}
</div>
</div>
</div>
</form>
#section Scripts{
#{
<partial name="_ValidationScriptsPartial" />
}
<script>
function validateInput() {
if (document.getElementById("imageBox").value == "") {
Swal.fire(
'Error!',
'Please upload an Image!',
'error'
)
return false;
}
return true;
}
</script>
<script>
$('.datepicker').datepicker({
startDate: new Date()
});
</script>
}
Controller Post Action
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Upsert(AdmisionVM admissionVM)
{
if (ModelState.IsValid)
{
var files = HttpContext.Request.Form.Files;
string webRootPath = _webHostEnvironment.WebRootPath;
if (admissionVM.AdmissionPatient.Id == 0)
{
//Creating
string upload = webRootPath + Constans.imagePath;
string fileName = Guid.NewGuid().ToString();
string extension = Path.GetExtension(files[0].FileName);
using (var fileStream = new FileStream(Path.Combine(upload, fileName + extension), FileMode.Create))
{
files[0].CopyTo(fileStream);
}
admissionVM.AdmissionPatient.Image = fileName + extension;
_db.AdmissionPacients.Add(admissionVM.AdmissionPatient);
}
else
{
//Updating
var objFromDb = _db.AdmissionPacients.AsNoTracking().FirstOrDefault(u => u.Id == admissionVM.AdmissionPatient.Id);
if (files.Count > 0)
{
string upload = webRootPath + Constans.imagePath;
string fileName = Guid.NewGuid().ToString();
string extension = Path.GetExtension(files[0].FileName);
var oldFile = Path.Combine(upload, objFromDb.Image);
if (System.IO.File.Exists(oldFile))
{
System.IO.File.Delete(oldFile);
}
using (var fileStream = new FileStream(Path.Combine(upload, fileName + extension), FileMode.Create))
{
files[0].CopyTo(fileStream);
}
admissionVM.AdmissionPatient.Image = fileName + extension;
}
else
{
admissionVM.AdmissionPatient.Image = objFromDb.Image;
}
_db.AdmissionPacients.Update(admissionVM.AdmissionPatient);
}
_db.SaveChanges();
return RedirectToAction("Index");
}
admissionVM.PatientSelectList = _db.Patients.Select(i => new SelectListItem
{
Text = i.FirstName + i.LastName,
Value = i.Id.ToString()
});
admissionVM.DoctorSelectList = _db.Doctors.Select(i => new SelectListItem
{
Text = i.Firstname + i.Lastname,
Value = i.Id.ToString()
});
return View(admissionVM);
}
try add name to this line:
<input type="checkbox" class="form-control" id="emergencyId">
to
<input name="Emergency" type="checkbox" class="form-control" id="emergencyId">
I'm trying to program an "add" button below an ASP.NET MVC table to dynamically append a blank row, and then have a submit button to save each row to the database with one click.
There are several similar questions on SO but none that I have been able to apply to this. I've been trying to apply this example but the "add" button is not appending new rows.
Model:
public class TableForm
{
public int Id { get; set; }
public List<TableFormData> TableFormDatas { get; set; }
}
public class TableFormData
{
public int Id { get; set; }
public string ClientSampleID { get; set; }
public string AdditionalComments { get; set; }
public string AcidStables { get; set; }
Razor view:
#model NewTestSix.Models.TableForm
#{
ViewData["Title"] = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Sample submission</legend>
<table id="submissionTable" class="table table-bordered">
<thead>
<tr>
<td>Sample ID</td>
<td>Additional Comments</td>
<td>Acid-stable amino acids</td>
</tr>
</thead>
<tr id="tablerow0">
<td>
<div class="editor-field">
<input class="text-box single-line" name="ClientSampleID[0]" type="text" value="" required="required" />
</div>
</td>
<td>
<div class="editor-field">
<input class="text-box single-line" name="AdditionalComments[0]" type="text" value="" required="required" />
</div>
</td>
<td>
<div class="editor-field">
<input class="text-box single-line" name="AcidStables[0]" type="text" value="" />
</div>
</td>
<td>
<button type="button" class="btn btn-primary" onclick="removeTr(0);">Delete</button>
</td>
<td>
</td>
</tr>
</table>
<p>
<button id="add" type="submit" class="btn btn-primary">Add</button>
</p>
<hr />
<p>
<input type="submit" value="Create" class="btn btn-default" />
</p>
</fieldset>
}
#section Scripts {
<script src="~/bundles/jqueryval.js" type="text/javascript">
var counter = 1;
$(function () {
$('#add').click(function () {
$('<tr id="tablerow' + counter + '"><td>' +
'<input type="text" class="text-box single-line" name="ClientSampleID[' + counter + ']" value="" required="required" />' +
'</td>' +
'<td>' +
'<input type="text" class="text-box single-line" name="AdditionalComments[' + counter + ']" value="" required="required" />' +
'</td>' +
'<td>' +
'<input type="text" class="text-box single-line" name="AcidStables[' + counter + ']" value="" required="required" />' +
'</td>' +
'<td>' +
'<button type="button" class="btn btn-primary" onclick="removeTr(' + counter + ');">Delete</button>' +
'</td>' +
'</tr>').appendTo('#submissionTable');
counter++;
return false;
});
});
function removeTr(index) {
if (counter > 1) {
$('#tablerow' + index).remove();
counter--;
}
return false;
}
</script>
I'm not too fussed about model binding with the controller at this stage, I just want to get this add button working. example controller:
[HttpPost]
public ActionResult Index(string any = "")
{
IList<TableForm> _TableForm = new List<TableForm>();
//Loop through the forms
for (int i = 0; i <= Request.Form.Count; i++)
{
var ClientSampleID = Request.Form["ClientSampleID[" + i + "]"];
var additionalComments = Request.Form["AdditionalComments[" + i + "]"];
var acidStables = Request.Form["AcidStables[" + i + "]"];
if (!String.IsNullOrEmpty(ClientSampleID))
{
_TableForm.Add(new TableForm { ClientSampleID = ClientSampleID, AcidStables = acidStables, AdditionalComments = additionalComments });
}
}
return View();
}
Thanks for any insights.
Current:
Desired after clicking "add" button:
Change your
<button id="add" type="submit" class="btn btn-primary">Add</button>
into
<button id="add" type="button" class="btn btn-primary">Add</button>
...as I don't think the "Add" button should ever make the browser do a form submission when clicked, it should only invoke your button's client-side 'click' event-handler.
Then remove src="~/bundles/jqueryval.js" part from your script element's opening tag: inline scripts cannot have a src="" attribute.
Like this:
<script type="text/javascript">
var counter = 1;
//... the rest of your code is here...
</script>
If you actually have a jqueryval.js file, put it in another <script> tag.
Here is the result you are expecting if I'm not mistaken.
var counter = 1;
$(function () {
$('#add').click(function () {
$('<tr id="tablerow' + counter + '"><td>' +
'<input type="text" class="text-box single-line" name="ClientSampleID[' + counter + ']" value="" required="required" />' +
'</td>' +
'<td>' +
'<input type="text" class="text-box single-line" name="AdditionalComments[' + counter + ']" value="" required="required" />' +
'</td>' +
'<td>' +
'<input type="text" class="text-box single-line" name="AcidStables[' + counter + ']" value="" required="required" />' +
'</td>' +
'<td>' +
'<button type="button" class="btn btn-primary" onclick="removeTr(' + counter + ');">Delete</button>' +
'</td>' +
'</tr>').appendTo('#submissionTable');
counter++;
return false;
});
});
function removeTr(index) {
if (counter > 1) {
$('#tablerow' + index).remove();
counter--;
}
return false;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<fieldset>
<legend>Sample submission</legend>
<table id="submissionTable" class="table table-bordered">
<thead>
<tr>
<td>Sample ID</td>
<td>Additional Comments</td>
<td>Acid-stable amino acids</td>
</tr>
</thead>
<tr id="tablerow0">
<td>
<div class="editor-field">
<input class="text-box single-line" name="ClientSampleID[0]" type="text" value="" required="required" />
</div>
</td>
<td>
<div class="editor-field">
<input class="text-box single-line" name="AdditionalComments[0]" type="text" value="" required="required" />
</div>
</td>
<td>
<div class="editor-field">
<input class="text-box single-line" name="AcidStables[0]" type="text" value="" />
</div>
</td>
<td>
<button type="button" class="btn btn-primary" onclick="removeTr(0);">Delete</button>
</td>
<td></td>
</tr>
</table>
<p>
<button id="add" type="button" class="btn btn-primary">Add</button>
</p>
<hr />
<p>
<input type="submit" value="Create" class="btn btn-default" />
</p>
</fieldset>
Let me know if it helps.
You can used jQuery jqGrid
It is jquery plugin which is free and open source. This is completely
Ajax enabled to display tabular data and to manipulate. Additionally,
we can apply different Jquery UI theme, see the demo.
Action Method: There is nothing here since we will be getting product details using Ajax in json format.
public ActionResult GetProducts(string sidx, string sord, int page, int rows)
{
var products = Product.GetSampleProducts();
int pageIndex = Convert.ToInt32(page) - 1;
int pageSize = rows;
int totalRecords = products.Count();
int totalPages = (int)Math.Ceiling((float)totalRecords / (float)pageSize);
var data = products.OrderBy(x => x.Id)
.Skip(pageSize * (page - 1))
.Take(pageSize).ToList();
var jsonData = new
{
total = totalPages,
page = page,
records = totalRecords,
rows = data
};
return Json(jsonData, JsonRequestBehavior.AllowGet);
}
And add this tag to target page
<table id="jqGrid"></table>
<div id="jqGridPager"></div>
After that in script section add this:
<script>
var myGrid = $('#jqGrid');
myGrid.jqGrid({
url: '/Home/GetProducts/',
datatype: "json",
contentType: "application/json; charset-utf-8",
mtype: 'GET',
colNames: ['ProductID', 'Name', 'Price', 'Department', 'Action'],
colModel: [
{ name: 'Id', key: true, width: 75 },
{ name: 'Name', key: true, width: 200 },
{ name: 'Price', key: true, width: 75 },
{ name: 'Department', key: true, width: 200 },
{ name: 'Edit', key: true, width: 100, editable: true, formatter: editButton }
],
rowNum: 4,
pager: '#jqGridPager',
gridview: true,
rownumbers: true,
pagerpos: 'center'
});
</script>
Original post is here
var counter = 2;
$(function () {
$('#add').click(function () {
$('<tr id="tablerow' + counter + '"><td>' +
'<input type="text" class="text-box single-line" name="ClientSampleID[' + counter + ']" value="" required="required" />' +
'</td>' +
'<td>' +
'<input type="text" class="text-box single-line" name="AdditionalComments[' + counter + ']" value="" required="required" />' +
'</td>' +
'<td>' +
'<input type="text" class="text-box single-line" name="AcidStables[' + counter + ']" value="" required="required" />' +
'</td>' +
'<td>' +
'<button type="button" class="btn btn-primary" onclick="removeTr(' + counter + ');">Delete</button>' +
'</td>' +
'</tr>').appendTo('#submissionTable');
counter++;
return false;
});
});
function removeTr(index) {
if (counter > 1) {
$('#tablerow' + index).remove();
counter--;
}
return false;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<fieldset>
<legend>Sample submission</legend>
<table id="submissionTable" class="table table-bordered">
<thead>
<tr>
<td>Sample ID</td>
<td>Additional Comments</td>
<td>Acid-stable amino acids</td>
</tr>
</thead>
<tr id="tablerow0">
<td>
<div class="editor-field">
<input class="text-box single-line" name="ClientSampleID[0]" type="text" value="" required="required" />
</div>
</td>
<td>
<div class="editor-field">
<input class="text-box single-line" name="AdditionalComments[0]" type="text" value="" required="required" />
</div>
</td>
<td>
<div class="editor-field">
<input class="text-box single-line" name="AcidStables[0]" type="text" value="" />
</div>
</td>
<td>
<button type="button" class="btn btn-primary" onclick="removeTr(0);">Delete</button>
</td>
<td></td>
</tr>
</table>
<p>
<button id="add" type="button" class="btn btn-primary">Add</button>
</p>
<hr />
<p>
<input type="submit" value="Create" class="btn btn-default" />
</p>
</fieldset>
On loading the application, table with list of items is displayed.
On clicking the save button, i want to write the list of items to excel.
When i click the save button, in the new request send to the controller,the list is empty.I do not prefer to write the list of table items to database.
Could anyone advice me on how to do handle this?
public IActionResult SaveReport(SalesParentViewModel salesParentViewModel)
{
if(salesParentViewModel.SalesDataModelItems != null)
{
var buffer = new StringBuilder();
buffer.AppendLine("#UserCode,SalesmanName,Date,ItemCode,ItemDescription,BrandCode,BrandName,ClientCode,Client,ClientBranchCode,Description, BranchSubChannel,TransactionAmount,Quantity");
salesParentViewModel.SalesDataModelItems.ToList().ForEach(item => buffer.AppendLine
(String.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13}", item.UserCode, item.SALESMANNAME, item.DATE, item.ItemCode, item.ITEMDESCRIPTION, item.BRANDCODE, item.BRANDNAME, item.ClientCode, item.Client, item.ClientBranchCode, item.Description, item.BRANCHSUBCHANNEL, item.TrxAmount, item.QTY
)));
System.IO.File.WriteAllText("c:\\temp\\file.csv", buffer.ToString());
}
return View();
}
View is as below:
#model MyStoreReports.ViewModels.SalesParentViewModel
#{
ViewBag.Title = "Sales Report";
}
#section scripts{
<script src="~/lib/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.js"></script>
<link rel="stylesheet"
href="http://cdn.datatables.net/1.10.2/css/jquery.dataTables.min.css">
<script type="text/javascript"
src="http://cdn.datatables.net/1.10.2/js/jquery.dataTables.min.js"></script>
<script type="text/javascript"
src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
}
<div class="container-fluid">
<div class="row">
<div class="col-sm-9">
<h1>Sales Report</h1>
</div>
</div>
<div>
<asp:Button id="btnFilter" class="btn btn-sm btn-info" runat="server" Text="Click Me!">
<i class="fa fa-filter"></i>Filter
</asp:Button>
#using (Html.BeginForm("SaveReport", "App", FormMethod.Post))
{
#Html.HiddenFor(model => model.SalesDataModelItems);
<asp:Button id="btnSave" class="btn btn-sm btn-info" onclick="location.href='#Url.Action("SaveReport","App")'" runat="server" Text="Click Me!">
<i class="fa fa-save"></i>Save
</asp:Button>
}
#*<a href="#" class="btn btn-sm btn-info">
<i class="fa fa-save"></i>Save
</a>*#
<a href="#" class="btn btn-sm btn-info">
<i class="fa fa-print"></i>Print
</a>
</div>
<div class="row">
<form method="post">
<asp:Panel id="pnlFilter" runat="server" GroupingText="This is a sample group text" HorizontalAlign="Center">
<div class="col-sm-10" style="background-color:lavenderblush;">
<div class="row">
<div class="col-sm-2">
<label asp-for="SalesViewModelInstance.StartDate">StartDate</label>
<div class="form-group">
<input asp-for="SalesViewModelInstance.StartDate" type="date" class="form-control" />
<span asp-validation-for="SalesViewModelInstance.StartDate" class="text-muted"></span>
</div>
</div>
<div class="col-sm-2">
<label asp-for="SalesViewModelInstance.EndDate">EndDate</label>
<div class="form-group">
<input asp-for="SalesViewModelInstance.EndDate" type="date" class="form-control" />
<span asp-validation-for="SalesViewModelInstance.EndDate" class="text-muted"></span>
</div>
</div>
<div class="row">
<div class="col-sm-1">
<input type="submit" value="Submit" class="btn btn-success" />
</div>
<div class="col-sm-1">
<a asp-controller="App" asp-action="Index" class="btn btn-default">Cancel</a>
</div>
</div>
</div>
</asp:Panel>
</form>
</div>
<div class="form-group">
#if (Model.SalesDataModelItems != null)
{
<div class="container" style="background-color:lavender;" >
<div class="row">
<div class="panel panel-primary">
<div class="panel-heading">
<h2>Report</h2>
</div>
<div class="VScrollTable">
<table id="myTable" class="table table-fixed table-responsive" align="left" cellspacing="0">
<thead>
<tr>
<th>UserCode</th>
<th>SalesmanName</th>
<th>Date</th>
<th>ItemCode</th>
<th>ItemDescription</th>
<th>BrandCode</th>
<th>BrandName</th>
<th>ClientCode</th>
<th>Client</th>
<th>ClientBranchCode</th>
<th>Description</th>
<th>BranchSubChannel</th>
<th>TransactionAmount</th>
<th>Quantity</th>
</tr>
</thead>
#foreach (var item in Model.SalesDataModelItems)
{
<tbody>
<tr>
<td>#item.UserCode</td>
<td>#item.SALESMANNAME</td>
<td>#item.DATE</td>
<td>#item.ItemCode</td>
<td>#item.ITEMDESCRIPTION</td>
<td>#item.BRANDCODE</td>
<td>#item.BRANDNAME</td>
<td>#item.ClientCode</td>
<td>#item.Client</td>
<td>#item.ClientBranchCode</td>
<td>#item.Description</td>
<td>#item.BRANCHSUBCHANNEL</td>
<td>#item.TrxAmount</td>
<td>#item.QTY</td>
</tr>
</tbody>
}
</table>
</div>
</div>
</div>
</div>
}
</div>
</div>
If no change is done in the model, why would you want to pass the entire model from the view to the controller?
Just pass an identifier of some sort like id, and get the data again in the controller and save it in Excel.
If you must pass the model back to the controller it can be done, but the data needs to be hidden inputs or editable input controls (text box, check box)
Your view should look similar to the following :
#model MyStoreReports.ViewModels.SalesParentViewModel
#{
ViewBag.Title = "Sales Report";
}
#section scripts{
<script src="~/lib/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.js"></script>
<link rel="stylesheet"
href="http://cdn.datatables.net/1.10.2/css/jquery.dataTables.min.css">
<script type="text/javascript"
src="http://cdn.datatables.net/1.10.2/js/jquery.dataTables.min.js"></script>
<script type="text/javascript"
src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
}
<div class="container-fluid">
<div class="row">
<div class="col-sm-9">
<h1>Sales Report</h1>
</div>
</div>
<div>
#using (Html.BeginForm("SaveReport", "App", FormMethod.Post))
{
<input id="brnSave" type="submit" class="btn btn-sm btn-info" value="Save" />
<div class="form-group">
#if (Model.SalesDataModelItems != null)
{
<div class="container" style="background-color:lavender;">
<div class="row">
<div class="panel panel-primary">
<div class="panel-heading">
<h2>Report</h2>
</div>
<div class="VScrollTable">
<table id="myTable" class="table table-fixed table-responsive" align="left" cellspacing="0">
<thead>
<tr>
<th>UserCode</th>
<th>SalesmanName</th>
<th>Date</th>
<th>ItemCode</th>
<th>ItemDescription</th>
<th>BrandCode</th>
<th>BrandName</th>
<th>ClientCode</th>
<th>Client</th>
<th>ClientBranchCode</th>
<th>Description</th>
<th>BranchSubChannel</th>
<th>TransactionAmount</th>
<th>Quantity</th>
</tr>
</thead>
#for (int i = 0; i < Model.SalesDataModelItems.Count; i++)
{
<tbody>
<tr>
<td>#Model.SalesDataModelItems[i].UserCode</td>
<td>#Model.SalesDataModelItems[i].SalesManName</td>
<td>#Model.SalesDataModelItems[i].SaleDate</td>
<td>#Model.SalesDataModelItems[i].ItemCode</td>
<td>#Model.SalesDataModelItems[i].ItemDescription</td>
<td>#Model.SalesDataModelItems[i].BrandCode</td>
<td>#Model.SalesDataModelItems[i].BrandName</td>
<td>#Model.SalesDataModelItems[i].ClientCode</td>
<td>#Model.SalesDataModelItems[i].ClientName</td>
<td>#Model.SalesDataModelItems[i].ClientBranchCode</td>
<td>#Model.SalesDataModelItems[i].Description</td>
<td>#Model.SalesDataModelItems[i].BranchSubChannel</td>
<td>#Model.SalesDataModelItems[i].TrxAmount</td>
<td>#Model.SalesDataModelItems[i].Quantity</td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].UserCode) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].SalesManName) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].SaleDate) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].ItemCode) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].ItemDescription) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].BrandCode) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].BrandName) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].ClientCode) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].ClientName) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].ClientBranchCode) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].Description) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].BranchSubChannel) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].TrxAmount) </td>
<td>#Html.HiddenFor(model => model.SalesDataModelItems[i].Quantity) </td>
</tr>
</tbody>
}
</table>
</div>
</div>
</div>
</div>
}
</div>
}
</div>
</div>
And like Tetsuya Yamamoto pointed out, avoid mixing asp web forms controls in asp.net MVC application
EDIT (After Maria comments) :
You can add an ajax call to save the data in excel on button press :
Controller Savereport method :
public ActionResult SaveReport()
{
try
{
// Get data from DB and save it in excel
return Json("Success save report");
}
catch (Exception ex)
{
return Json("Save report failure!" + ex.Message);
}
}
View :
#model MVCWebApplication.Controllers.SalesParentViewModel
#{
ViewBag.Title = "Sales Report";
}
#section scripts{
<link rel="stylesheet"
href="http://cdn.datatables.net/1.10.2/css/jquery.dataTables.min.css">
<script type="text/javascript"
src="http://cdn.datatables.net/1.10.2/js/jquery.dataTables.min.js"></script>
<script type="text/javascript"
src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
}
<div class="container-fluid">
<div class="row">
<div class="col-sm-9">
<h1>Sales Report</h1>
</div>
</div>
<div>
<input id="btnSave" type="button" class="btn btn-sm btn-info" data-url="#Url.Action("SaveReport","App")" value="Save" />
<div class="form-group">
#if (Model.SalesDataModelItems != null)
{
<div class="container" style="background-color:lavender;">
<div class="row">
<div class="panel panel-primary">
<div class="panel-heading">
<h2>Report</h2>
</div>
<div class="VScrollTable">
<table id="myTable" class="table table-fixed table-responsive" align="left" cellspacing="0">
<thead>
<tr>
<th>UserCode</th>
<th>SalesmanName</th>
<th>Date</th>
<th>ItemCode</th>
<th>ItemDescription</th>
<th>BrandCode</th>
<th>BrandName</th>
<th>ClientCode</th>
<th>Client</th>
<th>ClientBranchCode</th>
<th>Description</th>
<th>BranchSubChannel</th>
<th>TransactionAmount</th>
<th>Quantity</th>
</tr>
</thead>
#foreach (var item in Model.SalesDataModelItems)
{
<tbody>
<tr>
<td>#item.UserCode</td>
<td>#item.SalesManName</td>
<td>#item.SaleDate</td>
<td>#item.ItemCode</td>
<td>#item.ItemDescription</td>
<td>#item.BrandCode</td>
<td>#item.BrandName</td>
<td>#item.ClientCode</td>
<td>#item.ClientName</td>
<td>#item.ClientBranchCode</td>
<td>#item.Description</td>
<td>#item.BranchSubChannel</td>
<td>#item.TrxAmount</td>
<td>#item.Quantity</td>
</tr>
</tbody>
}
</table>
</div>
</div>
</div>
</div>
}
</div>
</div>
</div>
<script>
$(function () {
$('#btnSave').on('click', function () {
$.ajax({
url: $(this).data('url'),
type: 'post',
datatype: 'json',
contentType: 'application/json; charset=utf-8',
success: function (data) {
console.log(data);
},
error: function (xhr) {
console.log(JSON.parse(xhr.responseText));
}
});
});
});
</script>
This is the webmethod with ajax and jquery. when the EmpID is like 123,12,123456 it open the popup box and show the output as i want but when EmpID is like A001,ABC it show the error like "Error while retrieving data of :" how to solve...
Thanks in Advance
Query Data:-
$(document).on("click", ".editButton", function () {
$("#myModal").focus();
var id = $(this).attr("data-id");
console.log(id);
$("#btnUpdate").attr("edit-id", id);
//alert(id);
$.ajax({
type: "Post",
contentType: "application/json; charset=utf-8",
url: "Default3.aspx/EditData",
data: '{eid: ' + id + '}',
dataType: "json",
success: function (data) {
var empDetails = $.parseJSON(data.d);
$.each(empDetails, function (index, value) {
$("#FirstName1").val(value.EmpID);
$("#MiddleName1").val(value.EmpName);
$("#Surname1").val(value.EmpAddress);
//alert("hi");
});
},
error: function () {
alert("Error while retrieving data of :" + id);
}
});
});
});
Html Table:-
<div class="row">
<div class="col-lg-12">
<br />
<br />
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">
Admin Employee Details Tables
</div>
<!-- /.panel-heading -->
<div class="panel-body">
<div class="dataTable_wrapper">
<div id="dataTables-example_wrapper" class="dataTables_wrapper form-inline dt-bootstrap no-footer">
<div class="row">
<div class="col-sm-6">
<div class="dataTables_length" id="dataTables-example_length">
<label>
Show
<select name="dataTables-example_length" aria-controls="dataTables-example" class="form-control input-sm" id="select">
<option value="5">5</option>
<option value="10">10</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
entries</label>
</div>
</div>
<div class="col-sm-6">
<div id="dataTables-example_filter" class="dataTables_filter">
<label>Search:<input type="search" class="form-control input-sm" placeholder="" aria-controls="dataTables-example" id="searchtxt" /></label>
</div>
</div>
</div>
<div class="row">
<div class="table-responsive">
<table id="dataTables-example" class="table table-striped table-bordered table-hover dataTable no-footer " role="grid" aria-describedby="dataTables-example_info">
<thead>
<tr role="row">
<th class="sorting_asc" tabindex="0" aria-controls="dataTables-example" rowspan="1" colspan="1" style="width: 175px;" aria-sort="ascending" aria-label="Rendering engine: activate to sort column descending">Emp ID</th>
<th class="sorting" tabindex="0" aria-controls="dataTables-example" rowspan="1" colspan="1" style="width: 203px;" aria-label="Browser: activate to sort column ascending">Emp Name</th>
<th class="sorting" tabindex="0" aria-controls="dataTables-example" rowspan="1" colspan="1" style="width: 184px;" aria-label="Platform(s): activate to sort column ascending">Emp Address</th>
</tr>
</thead>
<tbody>
<% for (var data = 0; data < TableData.Rows.Count; data++)
{ %>
<tr class="gradeA odd " role="row">
<td class="sorting_1">
<%=TableData.Rows[data]["EmpID"]%>
</td>
<td>
<%=TableData.Rows[data]["EmpName"]%>
</td>
<td>
<%=TableData.Rows[data]["EmpAddress"]%>
</td>
<td>
<input type="button" class="btn btn-primary editButton" data-id="<%=TableData.Rows[data]["EmpID"] %>" data-toggle="modal" data-target="#myModal" name="submitButton" id="btnEdit" value="Edit" />
</td>
<td>
<input type="button" class="btn btn-primary deleteButton" data-id="<%=TableData.Rows[data]["EmpId"] %>" name="submitButton" id="btnDelete" value="Delete" />
</td>
</tr>
<% } %>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- /.table-responsive -->
</div>
<!-- /.panel-body -->
</div>
<!-- /.panel -->
</div>
</div>
</div>
C# Code-
[WebMethod]
public static string EditData(string eid)
{
string jsondata;
using(var con=new SqlConnection(ConnectString))
{
var query = "Select * from NewEmp where EmpID='" + eid + "' ";
using(var cmd=new SqlCommand(query, con))
{
using(var sda=new SqlDataAdapter())
{
cmd.Connection = con;
sda.SelectCommand = cmd;
TableData.Clear();
sda.Fill(TableData);
jsondata = JsonConvert.SerializeObject(TableData);
}
}
}
return jsondata;
}
Sounds like the ID field is set as an integer value somewhere, such that numbers will work but letters will throw an error. Your JSON looks messed up, too, with weird field mapping:
$("#FirstName1").val(value.EmpID);
$("#MiddleName1").val(value.EmpName);
$("#Surname1").val(value.EmpAddress);
FirstName may not map to EmpID well. Middlename to EmpName, etc.
But overall, it sounds like something is expecting an integer input and you're giving it letters. Look for that and either change the input expectation to varchar/string or change the input to only consist of numbers.
I have a div named 'BenefitsValue' in my page with display set to none..
<input id="Radio1" type="radio" name="bunit" value="1" onclick="onSample1()"
runat="server"/>Sample1
<input id="Radio2" type="radio" name="bunit" value="2" onclick="onSample2()"
runat="server"/>Sample2
<div id="BenefitsValue" style="display:none">
<table id="approverTable">
<tr id="rowtr" align="center">
<td>
<input type="text" id="From" size="11" maxlength="9"
class="gov-textbox" style="width: 100px;" />
</td>
<td>
<a id="addRangeLink" class="addRange" href="javascript:;"
onclick="AddTextBox();">AddRange</a>
</td>
</tr>
</table>
</div>
I will dynamically add multiple textboxes by clicking AddRange..
function AddRange() {
var val = "";
var oTable = document.getElementById('approverTable');
var rowCount = oTable.rows.length;
var row = oTable.insertRow(rowCount);
var cell0 = row.insertCell(0);
var innerhtml;
cell0.innerHTML = '<input type="text" id="From' + rowCount
+ '" size="11" maxlength="9" class="gov-textbox" style="width: 100px;" />';
}
If I select radiobutton1 I will display the div content and I will dynamically add multiple textboxes by clicking AddRange....
Then once I select radiobutton2 it must clear the newly added textboxes of that div and show me only the single text box which I specified inside the div..
I have used $("#BenefitsValue").empty(); to clear the contents but if I then use $("#BenefitsValue").show() to show it again it displays nothing...
How to overcome it?
How about this?
Live Demo
JS
function AddRange() {
var val = "";
var oTable = document.getElementById('approverTable');
var rowCount = oTable.rows.length;
var row = oTable.insertRow(rowCount);
row.className='dynamic';
var cell0 = row.insertCell(0);
var innerhtml;
cell0.innerHTML = '<input type="text" id="From' + rowCount + '" size="11" maxlength="9" class="gov-textbox" style="width: 100px;" />';
}
function onSample1(){
$('#BenefitsValue').show();
}
function onSample2(){
$('.dynamic').remove();
}
HTML
<input id="Radio1" type="radio" name="bunit" value="1" onclick="onSample1()" runat="server"/>Sample1
<input id="Radio2" type="radio" name="bunit" value="2" onclick="onSample2()" runat="server"/>Sample2
<div id="BenefitsValue" style="display:none">
<table id="approverTable">
<tr id="rowtr" align="center">
<td>
<input type="text" id="From" size="11" maxlength="9" class="gov-textbox" style="width: 100px;" />
</td>
<td>
<a id="addRangeLink" class="addRange" href="javascript:;" onclick="AddRange();">AddRange</a>
</td>
</tr>
</table>
</div>
Simply do a postback in the radio button change. so it will clear the content added by JavaScript and add default content to the page.
or else add a different class for dynamic contents and remove those by class name.
$('dynamic-class').remove();
Are you trying to hide an element from view?
$("#BenefitsValue").empty();
deletes the content. Instead, use
$("#BenefitsValue").hide();
Then you can use .show() to bring it back
You need to create a different <div> for the dynamically added text boxes. For example:
<table id="approverTable">
<tr id="rowtr" align="center">
<td>
<input type="text" id="From" size="11" maxlength="9"
class="gov-textbox" style="width: 100px;" />
</td>
<td>
<a id="addRangeLink" class="addRange" href="javascript:;"
onclick="AddTextBox();">AddRange</a>
</td>
<td>
<div id="dynamicallyAddedTextBoxesGoHere">
</div>
</td>
</tr>
</table>
Add your text boxes to $("#dynamicallyAddedTextBoxesGoHere").
Then in your javascript you can show/hide this div -
$("#dynamicallyAddedTextBoxesGoHere").hide();
$("#dynamicallyAddedTextBoxesGoHere").show();