View is as below:
#using (Html.BeginForm("AddCreditLeave", "AdminLeaveCredit"))
{
<div id="Container">
<table>
<tr style="background-color:#A9DDFF;color:Black;">
<td>Select</td>
<td>Staff Code</td>
<td>Name</td>
<td>Designation</td>
<td>AL</td>
<td>CL</td>
</tr>
#foreach (var person in Model.Empdetailslist)
{
<tr>
<td>
<input type="checkbox" name="sid" value="#person.staffcode" id="chk" />
</td>
<td>#Html.TextBoxFor(m => person.staffcode, new { #class = "ReadOnly", #readonly = "readonly", style = "width:180px; text-align:center" })</td>
<td>#Html.TextBoxFor(m => person.name, new { #class = "ReadOnly", #readonly = "readonly", style = "width:180px; text-align:center" })</td>
<td>#Html.TextBoxFor(m => person.designation, new { #class = "ReadOnly", #readonly = "readonly", style = "width:180px; text-align:center" })</td>
<td>#Html.TextBoxFor(m => person.ALLeave, new { style = "width:180px; text-align:center" })</td>
<td>#Html.TextBoxFor(m => person.CLLeave, new { style = "width:180px; text-align:center" })</td>
</tr>
}
</table>
}
First column is a Checkbox and I am showing ten rows.
Second column is a TextBox.
There is a Save button. On click of Save button, I want to pick values of second column from the Form Collection where Checkbox is checked.
How to do this?
This is how I would do this with a simplified example.
Working Fiddle
Model
public class AModel
{
public string Name { get; set; }
public string staffcode { get; set; }
public bool Checked { get; set; }
}
Note the Checked property
View for loop
#for(var i = 0; i < Model.Empdetailslist.Count; i++)
{
<tr>
<td>
#Html.HiddenFor(m => Model.Empdetailslist[i].Name)
#Html.HiddenFor(m => Model.Empdetailslist[i].staffcode)
#Html.CheckBoxFor(m = Model.Empdetailslist[i].Checked)
</td>
<td>
#Model[i].Name
</td>
</tr>
}
Note the for loop instead of foreach to enable model binding and the hidden fields to allow the values to be posted back to the controller
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/
Controller post
[HttpPost]
public ActionResult AddCreditLeave(YourModel model)
{
// property will be populated in model.Empdetailslist
return View(list);
}
Edit your View like this,
#using (Html.BeginForm("AddCreditLeave", "AdminLeaveCredit"))
{
<div id="Container">
<table>
<tr style="background-color:#A9DDFF;color:Black;">
<td>Select</td>
<td>Staff Code</td>
<td>Name</td>
<td>Designation</td>
<td>AL</td>
<td>CL</td>
</tr>
#foreach (var person in Model.Empdetailslist)
{
<tr>
<td>
<input type="checkbox" name="sid" value="#person.staffcode" id="#person.id" />
</td>
<td>#Html.TextBoxFor(m => person.staffcode, new { #class = "ReadOnly", #readonly = "readonly", style = "width:180px; text-align:center", id="staffcode_#person.id" })</td>
<td>#Html.TextBoxFor(m => person.name, new { #class = "ReadOnly", #readonly = "readonly", style = "width:180px; text-align:center", id="name_#person.id" })</td>
<td>#Html.TextBoxFor(m => person.designation, new { #class = "ReadOnly", #readonly = "readonly", style = "width:180px; text-align:center", id="designation_#person.id" })</td>
<td>#Html.TextBoxFor(m => person.ALLeave, new { style = "width:180px; text-align:center", id="ALLeave_#person.id" })</td>
<td>#Html.TextBoxFor(m => person.CLLeave, new { style = "width:180px; text-align:center", id="CLLeave_#person.id" })</td>
</tr>
}
</table>
<input type="button" onclick="SavePersons();" />
}
Use this code to get all selected person objects in an array.
<script type="text/javascript">
function SavePersons() {
var chkArr = document.getElementsByName('sid');
var selectedPersonsArr = new Array();
for(var i=0; i<chkArr.length; i++) {
if(chkArr[i].checked == true) {
var tmpPerson = new Object();
tmpPerson.id = chkArr[i].id;
tmpPerson.staffcode = document.getElementById('staffcode'+chkArr[i].id).value;
tmpPerson.name = document.getElementById('name'+chkArr[i].id).value;
tmpPerson.designation = document.getElementById('designation'+chkArr[i].id).value;
tmpPerson.ALLeave = document.getElementById('ALLeave'+chkArr[i].id).value;
tmpPerson.CLLeave = document.getElementById('CLLeave'+chkArr[i].id).value;
selectedArr.push(tmpPerson);
}
}
// Now array 'selectedPersonsArr' contains all selected Person objects
// here you can send these objects to your controller through AJAX
}
</script>
Hope it helps, thanks.
Related
I'm working on a page that will add the selected item from a dropdownlist to a List<> using button onclick.
The problem is the new selecteditem is overwriting the old value.
I simply would like to display a table from the selected items like this:
#---Model-----Remove-----
1 Model#1 x
2 Model#2 x
3 Model#3 x
4 Model#4 x
5 Model#5 x
-------------------------
Please see my code below,
ModelDescription.cs (model):
public class ModelDescription
{
public string modelDesc { get; set; }
}
method in controller:
public ActionResult StockOnHand()
{
bindModelDesc();
return View();
}
public void bindModelDesc()
{
var mc = db.ModelMaster_tbl.ToList();
List<SelectListItem> mclist = new List<SelectListItem>();
mclist.Add(new SelectListItem { Text = "--Select Model Type--", Value = "0" });
mclist.Add(new SelectListItem { Text = "--Select All Model--", Value = "1" });
foreach (var m in mc.Select(x => x.modelDesc).Distinct())
{
mclist.Add(new SelectListItem { Text = m, Value = m });
ViewBag.ModelDescs = mclist;
}
}
public ActionResult AddToListSOH(ModelDescription model)
{
var result = new List<ModelDescription>();
var res = db.ModelMaster_tbl.Where(x => x.modelDesc == model.modelDesc).SingleOrDefault();
result.Add(new ModelDescription { modelDesc = res.modelDesc });
return PartialView("AddToListSOH", result);
}
StockOnHand.cshtml (view):
#using (Html.BeginForm("StockOnHand", "PWSupermarket", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<div class="card">
<div class="card-body">
<form class="form-horizontal" role="form">
<h5 class="card-title">Stock On Hand</h5>
<p class="card-text">Generates the buildable quantity of a unit. </p>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#if (TempData["Message"] != null)
{
<span class="text-success"><strong>#TempData["Message"]</strong></span>
}
<div class="form-group">
#Html.LabelFor(model => model.modelDesc, htmlAttributes: new { #class = "col-md-3 control-label" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.modelDesc, ViewBag.ModelDescs as List<SelectListItem>, htmlAttributes: new { #class = "form-control" })
<button class="btn btn-outline-primary mt-1" type="button" onclick="AddToList()">Add To List</button>
</div>
</div>
<div id="foo1" class="mt-2">
</div>
</form>
</div>
</div>
}
Javascript to render the list of selected items partial view:
<script type="text/javascript">
function AddToList() {
$.ajax({
type: "Get",
url: '#Url.Action("AddToListSOH", "PWSupermarket")',
data: { modelDesc: $('#modelDesc').val() },
contentType: "application/html; charset=utf-8",
success: function (result) {
$('#foo1').html(result);
},
error: function (ex) { alert('failed.'); }
})
}
</script>
AddToListSOH.cshtml (Partial View for the list of selected items):
#model IEnumerable<MESProject_P1_csmvc.Models.ModelDescription>
<div>
#{ var count = 0;}
<table class="table table-sm table-striped" #*style="font-size: .7rem;"*#>
<caption>List of Models</caption>
<thead class="thead-dark">
<tr>
<th>#</th>
<th>Model</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#count
</td>
<td>
#Html.DisplayFor(i => item.modelDesc)
</td>
</tr>
}
</tbody>
</table>
</div>
screen shot of the page
Example to make SelectListItem List
private List<SelectListItem> ModelDeskList(ModelDesk modelDesc)
{
List<SelectListItem> selectList = new List<SelectListItem>();
selectList.Add(new SelectListItem { Value = "", Text = "------Select-----",Selected=true });
foreach (var model in modelDesc)
{
selectList.Add(new SelectListItem { Value = model.Id.ToString(), Text = model.Name});
}
return selectList;
}
I hope you find your solution from it
I solved my problem thanks to this link:
I'm storing the list of emails in Session["emails"] and every time I add a new email to the list, I just update it a pass it to a new list with all the records and at the end return the partial view.
.NET use partial view multiple times #Rolando F
I've changed some of my codes:
ModelDescription.cs
public class ModelDescription
{
public IEnumerable<string> modelsAdded { get; set; }
}
AddToListSOH method in controller:
public ActionResult AddToListSOH(string model)
{
if (Session["modelInputs"] == null)
{
List<string> temphandler1 = new List<string>();
temphandler1.Add(model);
Session["modelInputs"] = temphandler1;
}
else
{
List<string> temphandler2 = new List<string>();
temphandler2 = (List<string>)Session["modelInputs"];
temphandler2.Add(model);
Session["modelInputs"] = temphandler2;
}
var result = new ModelDescription { modelsAdded = (List<string>)Session["modelInputs"] };
return PartialView("AddToListSOH", result);
}
AddToListSOH.cshtml (Partial View):
<table class="table table-sm table-striped" #*style="font-size: .7rem;"*#>
<caption>List of Models</caption>
<thead class="thead-dark">
<tr>
<th>#</th>
<th>Model</th>
<th>Remove</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.modelsAdded)
{
<tr>
<td>
#count
</td>
<td>
#Html.DisplayFor(i => item)
</td>
<td>
Remove
</td>
</tr>
}
</tbody>
</table>
I have got a problem as follows:
I have created a table with dynamic rows by clicking "add button".A row includes some textboxes and one dropdown list. When I select a value from dropdown list as a term to automatically fill for other textboxes by data I get from the server. Now I just can apply for the first row.I don't know how to apply for the new row when click "add button".Please help me how to solve this problem. Thanks a lot.
This is my webpage
This is my controller code:
using Phieu90.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Phieu90.Controllers
{
public class XuLyPhieuController : Controller
{
XuLyPhieu90Entities1 db;
public XuLyPhieuController()
{
db = new XuLyPhieu90Entities1();
}
public ActionResult Index()
{
var lislinhkien = new SelectList(db.PA_LINHKIEN.ToList(), "ITEM_CODE", "ITEM_CODE");
ViewBag.LinhKien = lislinhkien;
List<PA_CHITIETPHIEU> listchitiet = new List<PA_CHITIETPHIEU> { new PA_CHITIETPHIEU { NHACUNGCAP = "", TENSP = "", MASP = "", MADUTOAN = "", SOLUONG = 0, DONVI = "", DONGIA = 0, SOTIEN = 0 } };
return View(listchitiet);
}
[HttpPost]
public JsonResult GetLinhKien(string Prefix)
{
var result = db.PA_LINHKIEN.SingleOrDefault(x => x.ITEM_CODE == Prefix);
return Json(result, JsonRequestBehavior.AllowGet);
}
}
}
This is my View:
<body>
<h2 style="text-align:center;margin-top:50px;margin-bottom:50px;">Bill Detail</h2>
#using (Html.BeginForm("PhieuMuaLinhKien", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div>Add New Row <i class="fas fa-plus-circle"></i></div>
<table id="dataTable" border="0" cellpadding="0" cellspacing="0" class="table table-bordered">
<tr>
<th class="title">Bill ID</th>
<th class="title">Supplier</th>
<th class="title">Item name</th>
<th class="title">Item code</th>
<th class="title">Reference code</th>
<th class="title">Quantity</th>
<th class="title">Unit</th>
<th class="title">Price</th>
<th class="title">Sum</th>
<th class="title">Delete</th>
</tr>
#if (Model != null && Model.Count > 0)
{
int j = 0;
foreach (var i in Model)
{
<tr style="border:1px solid black">
<td class="title">#Html.TextBoxFor(a => a[j].MACHITIET, new { #class = "form-control", #style = "width:120px;margin-left:12px;", #required = "required" })</td>
<td class="title">#Html.TextBoxFor(a => a[j].NHACUNGCAP, new { #class = "form-control", #style = "width:120px;margin-left:12px;", #required = "required", #id = "txtncc" })</td>
<td class="title">#Html.TextBoxFor(a => a[j].TENSP, new { #class = "form-control", #style = "width:120px;margin-left:12px;", #required = "required",#id= "txttensp" })</td>
#using (Html.BeginForm())
{
#*<td class="title">#Html.TextBoxFor(a => a[j].MASP, new { #class = "form-control view-data", #style = "width:120px;margin-left:12px;", #required = "required"})</td>*#
<td>#Html.DropDownListFor(a => a[j].MASP, ViewBag.LinhKien as SelectList, "--*--", new { #class = "form-control view-data", #style = "width:120px;margin-left:12px;", #required = "required",#id="ddllinhkien" })</td>
}
<td class="title">#Html.TextBoxFor(a => a[j].MADUTOAN, new { #class = "form-control", #style = "width:120px;margin-left:12px;", #required = "required" })</td>
<td class="title">#Html.TextBoxFor(a => a[j].SOLUONG, new { #class = "form-control", #style = "width:120px;margin-left:12px;", #required = "required" })</td>
<td class="title">#Html.TextBoxFor(a => a[j].DONVI, new { #class = "form-control", #style = "width:120px;margin-left:12px;", #required = "required" })</td>
<td class="title">#Html.TextBoxFor(a => a[j].DONGIA, new { #class = "form-control", #style = "width:120px;margin-left:12px;", #required = "required", #id = "txtdongia" })</td>
<td class="title">#Html.TextBoxFor(a => a[j].SOTIEN, new { #class = "form-control", #style = "width:120px;margin-left:12px;", #required = "required" })</td>
<td>
#if (j > 0)
{
Remove <i class="fas fa-trash"></i>
}
</td>
</tr>
j++;
}
}
</table>
}
<div style="margin-left:660px;margin-top:30px;">
<button type="submit" class="btn btn-primary" id="btnSubmit" style="">Save <i class="fas fa-save"></i></button>
</div>
enter code here
<script type="text/javascript">
$(document).ready(function () {
//1. Add new row
$("#addNew").click(function (e) {
e.preventDefault();
var $tableBody = $("#dataTable");
var $trLast = $tableBody.find("tr:last");
var $trNew = $trLast.clone().insertAfter($trLast);
var suffix = $trNew.find(':input:first').attr('name').match(/\d+/);
$trNew.find("td:last").html('<a href="#" class="btn btn-block btn-
danger remove">Xóa <i class="fas fa-trash"></i></a>');
$.each($trNew.find(':input'), function (i, val) {
// Replaced Name
var oldN = $(this).attr('name');
var newN = oldN.replace('[' + suffix + ']', '[' +
(parseInt(suffix) + 1) + ']');
$(this).attr('name', newN);
$(this).attr('id', newN);
//Replaced value
var type = $(this).attr('type');
if (type.toLowerCase() == "text") {
$(this).attr('value', '');
}
$(this).removeClass("input-validation-error");
});
$trLast.after($trNew);
var form = $("form")
.removeData("validator")
.removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse(form);
});
//2. Remove
//$('a.remove').on("click", function (e) {
// e.preventDefault();
// $(this).parent().parent().remove();
//});
$("#dataTable").on("click", ".remove", function () {
$(this).closest('tr').remove();
});
$('.view-data').change(function () {
var malk = $(this).val();
$.ajax({
url: "/XuLyPhieu/GetLinhKien",
type: "POST",
dataType: "json",
data: { Prefix: malk },
success: function (data) {
//do something
})
}
})
})
});
I'm new to Razor and I don't get why my selected value is not working.
var listItems = (List<Categories>)ViewBag.Categories;
Used in
#for (var i = 0; i < Model.TagActivities.Count; i++)
{
<tr>
#Html.HiddenFor(modelItem => Model.TagActivities[i].TAGActivityId, new { htmlAttributes = new { #class = "form-control" } })
#Html.HiddenFor(modelItem => Model.TagActivities[i].CategoryId, new { htmlAttributes = new { #class = "form-control"
<td>
#Html.EditorFor(modelItem => Model.TagActivities[i].ActivityName, new { htmlAttributes = new { #class = "form-control" } })
</td>
<td>
#Html.EditorFor(modelItem => Model.TagActivities[i].ActivityDescription, new { htmlAttributes = new { #class = "form-control" } })
</td>
<td>
#Html.DropDownListFor(modelItem => Model.TagActivities[i].Category.CategoryName, new SelectList(listItems, "CategoryId", "CategoryName", Model.TagActivities[i].Category.CategoryName), new { #class = "form-control" })
</td>
<td>
#Html.EditorFor(modelItem => Model.TagActivities[i].AlertMinutes, new { htmlAttributes = new { #class = "form-control" } })
</td>
<td>
#Html.EditorFor(modelItem => Model.TagActivities[i].IsDefault)
</td>
</tr>
}
Help please. Thank you.
It does not work because the selected value you pass is not of the same type at the objects in listItems. Once possible solution it would be to change the value you pass to the constructor of SelectList for the selected object:
new SelectList(listItems, "CategoryId", "CategoryName", Model.TagActivities[i].Category)
The listItems is a list of objects of type Categories. So as a selected object you should pass an object of this type.
I have an Index page with various filtering options on it, all included within a PagedList. They all appear to be working fine, except for the dates.
When I first filter by date, they work fine however when I click on a page number at the bottom, the search criteria for my date is disappearing.
I can see that I can passing the search term in the paged list, and I can see this date hit my controller and the filtering happen but the ViewBag.filterStartDate and ViewBag.filterEndDate just aren't binding back to my textboxes for some reason.
Index.cshtml:
#using PagedList.Mvc
#model PagedList.IPagedList<Job>
#using (Html.BeginForm("Index", "Jobs", FormMethod.Get, new { #class = "form-inline", role = "form" }))
{
<div class="panel panel-default">
<!-- Default panel contents -->
<div class="panel-heading">Filter Search Results</div>
<div class="panel-body">
<ul class="list-group">
<li class="list-group-item">
#Html.Label("By Id: ", new { #class = "col-md-4 control-label" })
#Html.TextBox("filterId", ViewBag.filterId as string, new { #class = "form-control" })
</li>
<li class="list-group-item">
#Html.Label("By Address Line 1: ", new { #class = "col-md-4 control-label" })
#Html.TextBox("filterAddress1", ViewBag.filterAddress1 as string, new { #class = "form-control" })
</li>
<li class="list-group-item">
#Html.Label("By Username: ", new { #class = "col-md-4 control-label" })
#Html.TextBox("filterUsername", ViewBag.filterUsername as string, new { #class = "form-control" })
</li>
<li class="list-group-item">
#Html.Label("By Contract: ", new { #class = "col-md-4 control-label" })
#Html.DropDownList("filterContract", null, "-- Select One --",
new { #class = "form-control" })
</li>
<li class="list-group-item">
#Html.Label("Date Created Start: ", new { #class = "col-md-4 control-label" })
#Html.TextBox("filterStartDate", ViewBag.filterStartDate as string, new { #class = "form-control date", type = "date" })
</li>
<li class="list-group-item">
#Html.Label("Date Created End: ", new { #class = "col-md-4 control-label" })
#Html.TextBox("filterFinishDate", ViewBag.filterFinishDate as string, new { #class = "form-control date", type = "date" })
</li>
<li class="list-group-item">
#Html.Label("By App: ", new { #class = "col-md-4 control-label" })
#Html.DropDownList("filterApp", null, "-- Select One --",
new { #class = "form-control" })
</li>
</ul>
<input type="submit" value="Apply Filter" class="btn btn-default" />
</div>
<div id="items" style="padding: 15px;">
#Html.Partial("Jobs", Model)
</div>
</div>
}
Jobs.cshtml:
#using System.Web.UI.WebControls
#using PagedList.Mvc
#model PagedList.IPagedList<Job>
#Html.ActionLink("Create New", "Create", null, new { #style = "float: left" })
#Html.ActionLink("Import Jobs", "Import", null, new { #style = "padding-left: 15px" })
#Html.ValidationSummary(true)
<table class="table">
<tr>
<th class="mobileview">
#Html.DisplayName("JobId")
</th>
<th>
#Html.DisplayName("Description")
</th>
<th class="mobileview">
#Html.DisplayName("Address")
</th>
<th class="mobileview">
#Html.DisplayName("Priority")
</th>
<th>
#Html.DisplayName("Date Created")
</th>
<th>
#Html.DisplayName("Username")
</th>
</tr>
#foreach (var item in Model)
{
<tr class="formrow">
<td class="mobileview">
#Html.DisplayFor(modelItem => item.JobId)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td class="mobileview">
#Html.DisplayFor(modelItem => item.Address1)
</td>
<td class="mobileview">
#Html.DisplayFor(modelItem => item.Priority)
</td>
<td>
#Html.DisplayFor(modelItem => item.DateCreated)
</td>
<td>
#Html.DisplayFor(modelItem => item.User.UserName)
</td>
<td class="mobileview">
#Html.ActionLink("View Job", "Details", new { id = item.JobId })
</td>
<td class="mobileview">
#if (item.Data != null)
{
#Html.ActionLink("View Data", "Details", "AppForms", new { id = item.Data.Id }, null)
}
else
{
#Html.DisplayFor(modelItem => item.Status)
}
</td>
</tr>
}
</table>
<p>Page #(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of #Model.PageCount</p>
#Html.PagedListPager(Model, page => Url.Action("Index", new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter, filterAddress1 = ViewBag.filterAddress1, filterId = ViewBag.filterId, filterUsername = ViewBag.filterUsername, filterStartDate = ViewBag.filterStartDate, filterFinishDate = ViewBag.filterFinishDate, filterApp = ViewBag.selectedApp, filterContract = ViewBag.selectedContract }), PagedListRenderOptions.Classic)
JobsController.cs:
public ActionResult Index(string sortOrder, string currentFilter, string filterId, string filterAddress1, int? page, String filterApp, String filterContract, DateTime? filterStartDate, DateTime? filterFinishDate, String filterUsername)
{
//...Other filtering
//Filter by date
if (filterStartDate != null)
{
jobs = jobs.Where(x => x.DateCreated >= filterStartDate);
//ViewBag.filterStartDate = filterStartDate.Value.Year + "-" + filterStartDate.Value.Month + "-" + filterStartDate.Value.Day;
ViewBag.filterStartDate = filterStartDate;
}
if (filterFinishDate != null)
{
//Make sure we're checking to the end of the end date (ie 01/01/2015 23:59:59)
filterFinishDate = filterFinishDate.Value.AddHours(23).AddMinutes(59).AddSeconds(59);
jobs = jobs.Where(x => x.DateCreated <= filterFinishDate);
//ViewBag.filterFinishDate = filterFinishDate.Value.Year + "-" + filterFinishDate.Value.Month + "-" + filterFinishDate.Value.Day;
ViewBag.filterFinishDate = filterFinishDate;
}
int pageSize = int.Parse(ConfigurationManager.AppSettings["MaxPageItemCount"]);
int pageNumber = page ?? 1;
return this.View(jobs.ToPagedList(pageNumber, pageSize));
}
#Html.TextBox() can pull values out of the ModelState or ViewData.
Try building the html for the date input manually like this:
<input type="date" name="filterStartDate" id="filterStartDate" class="form-control date" value="#ViewBag.filterStartDate.ToString("yyyy-MM-dd")"/>
Resolved the issue by manually creating the date inputs rather tahn relying on Razor to do it for me!
#if (ViewBag.filterStartDate != null)
{
<input type="date" name="filterStartDate" id="filterStartDate" value="#ViewBag.filterStartDate.ToString("yyyy-MM-dd")" />
}
else
{
<input type="date" name="filterStartDate" id="filterStartDate" value="" />
}
I have a view that is populated by a foreach loop. Each row in the table has a dropdown list and I want to use the value of that dropdown list to calculate another value on the same row in the view.
I am new to Jquery and have tried everything but it only works on the first row in the table.
Any advice would be appreciated.
View Code
#model PagedList.IPagedList<VmShoppingCartCatalogue>
#using Mojito.Domain.ViewModels
#using PagedList.Mvc;
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />
<script src="~/Scripts/jquery-1.8.2.min.js" type="text/javascript"></script>
#section Scripts {
<script>
$(document).ready(function () {
updatePrice();
});
function updatePrice() {
$('#TypeOfSubscription').each(function (e) {
$('#TypeOfSubscription').change(function () {
var subscriptionType = $('#TypeOfSubscription').val();
var name = $('#Name').val();
var price = $('#Price').val();
var totalUsers = $('#NoOfUsers').val();
$.ajax({
url: "#Url.Action("GetSubscriptionPrice", "ShoppingCartCatalogue", new {Area = "ECommerce"})",
contentType: 'application/html; charset=utf-8',
type: 'GET',
dataType: 'text',
data: { 'subscriptionType': subscriptionType, 'name': name, 'price': price, 'totalUsers': totalUsers }
})
.success(function (result) {
$('#Price').val(result);
$('#price').text(result);
})
.error(function (xhr, textStatus, errorThrown) {
if (xhr.status == 500) {
alert('Internal error: ' + xhr.responseText);
} else {
alert('Unexpected error.');
};
});
});
});
}
</script>
}
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Mojito Products</h2>
<div class="col-md-9"></div>
<div class="col-md-3">
#using (Html.BeginForm("ShoppingCartCatalogue", "ShoppingCartCatalogue", FormMethod.Get))
{
<p>
#Html.TextBox("SearchString", ViewBag.CurrentFilter as string)
<input type="submit" value="Search" />
</p>
}
</div>
<div class="container col-md-12">
<table class="table col-md-12">
<tr>
<th>
#Html.DisplayNameFor(model => model.FirstOrDefault().ImageData)
</th>
<th>
#Html.ActionLink("Category", "ShoppingCartCatalogue", new { sortOrder = ViewBag.SortByCategory, currentFilter = ViewBag.CurrentFilter })
</th>
<th>
#Html.ActionLink("Product", "ShoppingCartCatalogue", new { sortOrder = ViewBag.SortByProduct, currentFilter = ViewBag.CurrentFilter })
</th>
<th>
#Html.DisplayNameFor(model => model.FirstOrDefault().Description)
</th>
<th>
#Html.DisplayNameFor(model => model.FirstOrDefault().TypeOfSubscription)
</th>
<th>
#Html.ActionLink("Price per user", "ShoppingCartCatalogue", new { sortOrder = ViewBag.SortByPrice, currentFilter = ViewBag.CurrentFilter })
</th>
<th>
#Html.DisplayNameFor(model => model.FirstOrDefault().NoOfUsers)
</th>
<th>
#Html.DisplayNameFor(model => model.FirstOrDefault().TotalPrice)
</th>
<th>
</th>
</tr>
#foreach (VmShoppingCartCatalogue t in Model)
{
using (Html.BeginForm("AddToCart", "ShoppingCart", FormMethod.Post))
{
<tr>
<td>
#if (t.ImageData != null)
{
<div class="pull-left" style="margin-right: 10px">
<img class="img-thumbnail" width="60" height="75"
src="#Url.Action("GetImage", "ShoppingCartCatalogue",
new { t.MojitoProductId })" />
</div>
}
</td>
<td>
#Html.DisplayFor(modelItem => t.Category, new { Name = "Category", id = "Category" })
</td>
<td>
#Html.DisplayFor(modelItem => t.Name, new { Name = "Name", id = "Name" })
</td>
<td>
#Html.DisplayFor(modelItem => t.Description, new { Name = "Description", id = "Description" })
</td>
<td>
#Html.EnumDropDownListFor(modelItem => t.TypeOfSubscription, new { Name = "TypeOfSubscription", id = "TypeOfSubscription", align = "left" })
</td>
<td>
<div id="price">#Html.DisplayFor(modelItem => t.Price, new { Name = "Price", id = "Price" })</div>
</td>
<td>
#Html.TextBoxFor(modelItem => t.NoOfUsers, new { Name = "NoOfUsers", id = "NoOfUsers", type = "number", min = "1", width = "10" })
</td>
<td>
#Html.DisplayFor(modelItem => t.TotalPrice, new { Name = "TotalPrice", id = "TotalPrice" })
</td>
<td>
#if (Request.Url != null)
{
#Html.HiddenFor(modelItem => t.TypeOfSubscription, new { Name = "TypeOfSubscription", id = "TypeOfSubscription" })
#Html.HiddenFor(modelItem => t.NoOfUsers, new { Name = "NoOfUsers", id = "NoOfUsers" })
#Html.HiddenFor(modelItem => t.MojitoProductId, new { Name = "MojitoProductId", id = "MojitoProductId" })
#Html.HiddenFor(modelItem => t.Category, new { Name = "Category", id = "Category" })
#Html.HiddenFor(modelItem => t.Name, new { Name = "Name", id = "Name" })
#Html.HiddenFor(modelItem => t.Description, new { Name = "Description", id = "Description" })
#Html.HiddenFor(modelItem => t.Price, new { Name = "Price", id = "Price" })
#Html.HiddenFor(modelItem => t.TotalPrice, new { Name = "TotalPrice", id = "TotalPrice" })
#Html.Hidden("returnUrl", Request.Url.PathAndQuery)
<input type="submit" class="btn btn-success" value="Add to cart" />
}
</td>
</tr>
}
}
</table>
</div>
<div class="col-md-12">
Page #(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of #Model.PageCount
</div>
#Html.PagedListPager(Model, page => Url.Action("ShoppingCartCatalogue",
new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))
The problem is you are rendering duplicate IDs for the element in each row, so var subscriptionType = $('#TypeOfSubscription').val(); will get the value of the first element with id="TypeOfSubscription" (the one in the first row).
Add a classname for TypeOfSubscription, then get the associated elements in the row using relative selectors. For example
$('.TypeOfSubscription').change(function () {
var columns = $(this).closest('tr').children('td');
var subscriptionType = $(this).val();
var price = columns.eq(8).find('input').eq(6).val(); // assume you want the hidden input value but again you have 2 duplicate ID's within the same row!
var totalUsers = columns.eq(6).find('input').val();
Note: there is no need to set the id and name attributes using #Html.HiddenFor(modelItem => t.TypeOfSubscription, new { Name = "TypeOfSubscription", id = "TypeOfSubscription" }). Both attributes are based on the property name (TypeOfSubscription) so they will both be "TypeOfSubscription" any way, and html helpers ignore any attempt to manually set the name attribute.
Note 2: apart from the invalid html because of the duplicate ID's, <form> elements cannot be child elements of <table>