In my MVC 3 project, I am using quite a strange bit of code to select a row in a table and perform some updates. My problem is that I am unsure how to validate whether the row has been selected.
Here is the code in my view:
<p><i>Select an invoice from the grid below:</i></p>
#if (!string.IsNullOrEmpty(TempData["PaymentError"] as string))
{
<div id="error" style="margin: 0 auto; width: 400px;">
<p style="width: 400px;"><img src="../../Content/images/errorsm.png" style="vertical-align: middle; padding: 5px;"/><span style="color: #A62000;font-weight: bold;">#(TempData["PaymentError"] as string)</span></p>
</div>
}
<table id="database">
<tr>
<th></th>
<th>
Invoice Number
</th>
<th>
Invoice Amount
</th>
<th>
Invoice Month
</th>
<th>
Invoice Status
</th>
<th>
Client
</th>
<th></th>
</tr>
#using (Html.BeginForm("Confirm", "Invoice"))
{
foreach (var item in Model)
{
string selectedRow = "";
if (item.InvoiceNumberID == ViewBag.InvoiceNumberID)
{
selectedRow = "selectedRow";
}
<tr class="#selectedRow" valign="top">
<td>
<a href='javascript:void(0)' class='select' data-id=#item.InvoiceNumberID >Select</a>
</td>
<td>
#Html.DisplayFor(modelItem => item.InvoiceNumberID)
</td>
<td>
#Html.DisplayFor(modelItem => item.InvoiceAmount)
</td>
<td>
#Html.DisplayFor(modelItem => item.InvoiceMonth)
</td>
<td>
#Html.DisplayFor(modelItem => item.InvoiceStatus)
</td>
<td>
#Html.DisplayFor(modelItem => item.Client.FullName)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.InvoiceNumberID }) |
#Html.ActionLink("Details", "Details", new { id = item.InvoiceNumberID }) |
#Html.ActionLink("Delete", "Delete", new { id = item.InvoiceNumberID })
</td>
</tr>
}
<input type='hidden' id='id' name='id' value='0' />
<p>
<a href='#Url.Action("CreateBulkInvoices", "Invoice")'>Generate Invoices</a>
</p>
<table>
<br />
<i>Select an amount below to confirm as paid:</i><br /><br />
<tr><td><b>Monthly Amounts:</b></td><td><b>Weekly Amounts:</b></td></tr>
<tr><td>Private Lesson (1 Hour) #Html.RadioButton("InvoiceAmount", "640", true) R640.00<br /></td><td>Private Lesson (1 Hour) #Html.RadioButton("InvoiceAmount", "140", true) R160.00<br /> </td></tr>
<tr><td>Private Lesson (1/2 Hour) #Html.RadioButton("InvoiceAmount", "350", true) R350.00<br /></td><td>Private Lesson (1 Hour) #Html.RadioButton("InvoiceAmount", "87.50", true) R87.50<br /></td></tr>
<tr><td>Group Lesson (1 Hour) #Html.RadioButton("InvoiceAmount", "460", true) R460.00</td> <td>Private Lesson (1 Hour) #Html.RadioButton("InvoiceAmount", "115", true) R115.00<br /></td></tr>
<tr><td>Custom Amount #Html.RadioButton("InvoiceAmount", "115", true) #Html.TextBox("InvoiceCustomAmount")<br /></td></tr>
</table>
<br />
<p><i>Select a payment type:</i>
</p>
<p>#Html.RadioButton("PaymentType", "EFT", true) EFT<br />
#Html.RadioButton("PaymentType", "Credit Card", true) Credit Card<br />
#Html.RadioButton("PaymentType", "Cheque", true) Cheque
</p>
<p><input type="submit" value="Confirm" /></p>
}
</table>
<br />
<script type='text/javascript'>
$('.select').click(function(){
$('#id').val($(this).attr('data-id'));
$(this).closest('table').find('tr').removeClass('selectedRow');
$(this).closest('tr').addClass('selectedRow');
});
</script>
And the code in my controller is:
public ActionResult Confirm(int id, long InvoiceAmount, string PaymentType, float? InvoiceCustomAmount)
{
var invoice = db.Invoice.Find(id);
//now validate that if the logged in user is authorized to select and confirm this invoice or not.
var clientPayment = new ClientPayments();
clientPayment.InvoiceNumberID = id;
if (InvoiceAmount == 115)
{
InvoiceAmount = (long)InvoiceCustomAmount;
}
var TotalPayments = invoice.ClientPayments.Sum(payment => payment.PaymentAmount) + InvoiceAmount;
if (TotalPayments > invoice.InvoiceAmount)
{
TempData["PaymentError"] = "You cannot pay more than the invoice amount";
return RedirectToAction("Index");
}
clientPayment.PaymentAmount = InvoiceAmount;
clientPayment.PaymentType = PaymentType;
clientPayment.PaymentDate = DateTime.Now;
db.ClientPayments.Add(clientPayment);
if (TotalPayments != invoice.InvoiceAmount)
{
invoice.InvoiceStatus = "Partly Paid";
}
else
{
invoice.InvoiceStatus = "Confirmed";
}
// You donĀ“t need this, since "invoice" was retrieved earlier in the method the database context
// knows that changes have been made to this object when you call "SaveChanges".
// db.Entry(invoices).State = EntityState.Modified;
db.SaveChanges();
return View();
}
Is there an easy way to validate if the row has been selected when the form is submitted?
Thanks,
Amy
So, what about not enabling the submit button unless you've actually selected something? You could initially set your submit button to be disabled. Something like this:
<input type="submit" value="Confirm" class="mysubmit" />
$(document).ready(function () {
$('.mysubmit').attr('disabled', 'disabled');
// whatever else...
});
Re-enabling can be done by removing that attribute:
$('.mysubmit').removeAttr('disabled');
Would think you could modify your click to do this:
<script type='text/javascript'>
$('.select').click(function(){
$('#id').val($(this).attr('data-id'));
$(this).closest('table').find('tr').removeClass('selectedRow');
$(this).closest('tr').addClass('selectedRow');
// enable your submit button
$('.mysubmit').removeAttr('disabled');
});
</script>
Didn't test it but seems like that would ensure that the user clicked a select class link before clicking the submit button.
Related
I have tried several approaches, and as I'm new to Razor Pages in ASP.NET Core I'm blocked. Could anybody help me please? It must be something trivial but I googled quite a lot and I can't find a suitable way. I don't want to use jquery or any other javascript library.
Here is the relevant code:
<form method="post">
<table>
<thead>
<tr>
<th>
Text 1
</th>
<th>
Text 2
</th>
<th>
Text 3
</th>
</tr>
</thead>
<tbody>
#foreach(var item in Model.GridRows)
{
<tr>
<td>
<input type="hidden" asp-for="#item.Id" />
</td>
<td>
#Html.EditorFor(modelItem => item.Text1)
</td>
<td>
#Html.EditorFor(modelItem => item.Text2)
</td>
<td>
#Html.EditorFor(modelItem => item.Text3)
</td>
<td>
<input type="submit" value="Save" class="btn btn-primary"/>
</td>
</tr>
}
</tbody>
</table>
</form>
public async Task<IActionResult> OnPostAsync(int id)
{
if (!ModelState.IsValid)
{
return Page();
}
var gridRowUpdate = await _context.GridRows.FindAsync(id);
if (gridRowUpdate == null)
{
return NotFound();
}
if(await TryUpdateModelAsync<GridRow>(gridRowUpdate, "GridRow", g => g.Text1, g => g.Text2, g => g.Text3))
{
await _context.SaveChangesAsync();
}
return RedirectToPage("./Index");
}
IF you want to click each save button to send the Id of that row, You can just follow below simple demo without any jquery or any other javascript library.
<table>
<thead>
<tr>
<th>
Text 1
</th>
<th>
Text 2
</th>
<th>
Text 3
</th>
</tr>
</thead>
<tbody>
#foreach(var item in Model.test)
{
<form method="post" >
<tr>
<td>
<input type="hidden" name="Id" value="#item.Id" />
</td>
<td>
#Html.EditorFor(modelItem => item.Text1)
</td>
<td>
#Html.EditorFor(modelItem => item.Text2)
</td>
<td>
#Html.EditorFor(modelItem => item.Text3)
</td>
<td>
<input type="submit" value="Save" class="btn btn-primary"/>
</td>
</tr>
</form>
}
</tbody>
</table>
I have implemented a save button in my .NET application on the index page. When I click it, it loads, but does not save anything. I am just using the index page for checkboxes. If I uncheck something and save it, it saves, but also unchecks everything else in that row. Nothing happens when I try to check something. Here is the code I'm using:
Index.cshtml
#using (Html.BeginForm("save", "drnos"))
{
<input type="submit" value="Save" />
}
An example of one of my check box fields:
<td>
#Html.EditorFor(modelItem => item.Soft)
#Html.ValidationMessageFor(modelItem => item.Soft)
</td>
drnosController.cs
[HttpPost]
public ActionResult save(Doctor doc)
{
System.Diagnostics.Debug.WriteLine("Save Called");
db.Entry(doc).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
Here is the whole HTML file:
#model PagedList.IPagedList<drnosv6.Models.Doctor>
#using PagedList.Mvc;
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />
#{
ViewBag.Title = "Index";
}
<h2>Doctors</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
#using (Html.BeginForm()) //insert the search bar
{
<p>
Find by First Name, Last Name, or RVH ID: #Html.TextBox("SearchString")
<input type="submit" value="Search" />
</p>
}
#using (Html.BeginForm("save", "drnos"))
{
<input type="submit" value="Save" />
}
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$('tr:even').addClass('alt-row-class');
});
</script>
<p>
</p>
<p>Click on a column header to sort by that column</p>
<table>
<tr>
<th>
#Html.ActionLink("RVH ID", "Index", new { sortOrder = ViewBag.IDSortParm })
</th>
<th>
#Html.ActionLink("Last Name", "Index", new { sortOrder = ViewBag.LastSortParm })
</th>
<th>
#Html.ActionLink("First Name", "Index", new { sortOrder = ViewBag.FirstSortParm })
</th>
<th>
Middle Initial
</th>
<th>
Degree
</th>
<th>
Group
</th>
<th>
Adm Priv
</th>
<th>
#Html.ActionLink("QCPR", "Index", new { sortOrder = ViewBag.QCPRSortParm })
</th>
<th>
#Html.ActionLink("Keane", "Index", new { sortOrder = ViewBag.KeaneSortParm })
</th>
<th>
#Html.ActionLink("Orsos", "Index", new { sortOrder = ViewBag.OrsosSortParm })
</th>
<th>
#Html.ActionLink("Soft", "Index", new { sortOrder = ViewBag.SoftSortParm })
</th>
<th>
#Html.ActionLink("3M", "Index", new { sortOrder = ViewBag.threeMSortParm })
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
using (Html.BeginForm("Save", "Doctor", FormMethod.Post))
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.RVH_ID_)
</td>
<td>
#Html.DisplayFor(modelItem => item.Last_Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.First_Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Middle_Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Degree1)
</td>
<td>
#Html.DisplayFor(modelItem => item.Group)
</td>
<td>
#Html.DisplayFor(modelItem => item.AdmPriv)
</td>
<td>
#Html.DisplayFor(modelItem => item.QCPR)
</td>
<td>
#Html.EditorFor(modelItem => item.Keane)
#Html.ValidationMessageFor(modelItem => item.Keane)
</td>
<td>
#Html.EditorFor(modelItem => item.Orsos)
#Html.ValidationMessageFor(modelItem => item.Orsos)
</td>
<td>
#Html.EditorFor(modelItem => item.Soft)
#Html.ValidationMessageFor(modelItem => item.Soft)
</td>
<td>
#Html.DisplayFor(modelItem => item.C3M)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.RVH_ID_ })
#Html.ActionLink("Details", "Details", new { id = item.RVH_ID_ })
</td>
</tr>
}
}
</table>
<p>
<input type="submit" value="Save" />
</p>
<br />
Page #(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of #Model.PageCount
#Html.PagedListPager(Model, page => Url.Action("Index", new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))
Your BeginForm or ActionLink has to point to ActionResult Edit.
When a form is submitted, only the inputs declared within that form get submitted. You only have the submit button in your form, so there are no other fields to fill out your Doctor structure. You need to have your save button on the same form as all your other fields.
I am trying to pass values from a view to a controller in MVC. I am using a ViewModel and normally the values would bind to the properties as long as the names are the same. However because the values are generated via a foreach loop the names of the values do not match the names of the properties in the view model.
I am working around this by assigning the values to a variable in Razor. However one of my values is in a text box on the form and the value is not being passed to the controller and I cannot work out why.
I get a null exception when clicking the button.
VIEW Code is below:
#model PagedList.IPagedList<Mojito.Domain.ViewModels.ShoppingCartProductItem>
#using System.Web.UI.WebControls
#using PagedList.Mvc;
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Mojito Products</h2>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.FirstOrDefault().Description)
</th>
<th>
#Html.ActionLink("Price", "Index", new { sortOrder = ViewBag.SortByPrice, currentFilter = ViewBag.CurrentFilter })
</th>
<th>
#Html.DisplayNameFor(model => model.FirstOrDefault().Quantity)
</th>
<th>
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#Html.DisplayFor(modelItem => item.Price)
</td>
<td>
#Html.TextBoxFor(modelItem => item.Quantity)
</td>
<td>
#{string Description = item.Description;}
#{decimal Price = item.Price;}
#{int Quantity = item.Quantity; }
#using (Html.BeginForm("AddToCart", "ShoppingCart", FormMethod.Post))
{
<div class="pull-right">
#if (Request.Url != null)
{
<input type="text" hidden="true" name="Description" value=#Description />
<input type="text" hidden="true" name="Price" value=#Price />
<input type="text" hidden="true" name="Quantity" value=#Quantity />
#Html.Hidden("returnUrl", Request.Url.PathAndQuery)
<input type="submit" class="btn btn-success" value="Add to cart" />
}
</div>
}
</td>
</tr>
}
</table>
<div class="col-md-12">
Page #(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of #Model.PageCount
</div>
#Html.PagedListPager(Model, page => Url.Action("Index",
new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))
Controller Code below
public ActionResult AddToCart(Cart cart, MojitoProduct product, string returnUrl, int Quantity =1)
{
if (product != null)
{
cart.AddItem(product, Quantity);
}
return RedirectToAction("Index", new { returnUrl });
}
Do not use foreach. Use a for-loop instead and within this, qualify the full path to your properties using the index.
Better yet: use a Edit- or DisplayTemplate for the ShoppingCartProductItem. This will also keep your path.
You have to use for loop instead of foreach:
#for (int i=0;i < Model.Count; i++)
{
<tr>
<td>
#Html.DisplayFor(modelItem => Model[i].Description)
</td>
<td>
#Html.DisplayFor(modelItem => Model[i].Price)
</td>
<td>
#Html.TextBoxFor(modelItem => Model[i].Quantity)
</td>
..........................
..........................
..........................
}
you can also post all using one form by posting List<ShoppingCartProductItem>, see Model Binding To A List
Your textboxes so values out of the form.
Try like below
#using (Html.BeginForm("AddToCart", "ShoppingCart", FormMethod.Post))
{
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#Html.DisplayFor(modelItem => item.Price)
</td>
<td>
#Html.TextBoxFor(modelItem => item.Quantity)
</td>
<td>
#{string Description = item.Description;}
#{decimal Price = item.Price;}
#{int Quantity = item.Quantity; }
<div class="pull-right">
#if (Request.Url != null)
{
<input type="text" hidden="true" name="Description" value=#Description />
<input type="text" hidden="true" name="Price" value=#Price />
<input type="text" hidden="true" name="Quantity" value=#Quantity />
#Html.Hidden("returnUrl", Request.Url.PathAndQuery)
<input type="submit" class="btn btn-success" value="Add to cart" />
}
</div>
</td>
</tr>
}
}
I resolved this in the short term by using new and forcing the name of the parameter.
#Html.HiddenFor(modelItem => t.NoOfUsers, new { Name = "NoOfUsers", id = "NoOfUsers" })
I would like to disable a cancel button if the the record field "Status" is already recorded as cancelled. I already know how to disable a button but the problem is how would the jquery know that the record field "Status" is Cancelled.
Here Are the Codes
#foreach (var rDetail in Model.Customers.ToList()) {
<tr>
<td>
#Html.DisplayFor(model => rDetail.DateEntry)
</td>
<td>
#Html.DisplayFor(model => rDetail.DateStart)
</td>
<td>
#Html.DisplayFor(model => rDetail.DateEnd)
</td>
<td>
#Html.DisplayFor(model => rDetail.Status.Name)
</td>
<td>
#Html.DisplayFor(model => rDetail.UserCode)
</td>
<td>
#Html.DisplayFor(model => rDetail.DateModified)
</td>
<td>
#Html.DisplayFor(model => rDetail.Remarks)
</td>
<td>
#Html.ActionLink("Details", "Details", "RoomReservation", new { id = rDetail.Id}, null) |
#using (Html.BeginForm("CancelReservation", "Rooms", new { roomId = Model.Id, reservationId = rDetail.Id, methodId = 0})) {
<input type="submit" value="Cancel" class ="cancelSubmit"/>
}
</td>
</tr>
Any help will be appreciated, thanks :)
If you know the status is cancelled you can disable it in the Razor itself.
<td>
#Html.ActionLink("Details", "Details", "RoomReservation", new { id = rDetail.Id}, null);
#if(rDetail.Status.Name.Equals("cancelled"))
{
<input type="submit" value="Cancel" class ="cancelSubmit" disabled/>
}
else
{
#using (Html.BeginForm("CancelReservation", "Rooms", new { roomId = Model.Id, reservationId = rDetail.Id, methodId = 0})) {
<input type="submit" value="Cancel" class ="cancelSubmit"/>
}
}
</td>
If you want to do it jquery way:-
$(function(){
$('.cancelSubmit').each(function(){
if($(this).closest('tr').find('#Status_Name').text() === 'cancelled')
{
$(this).prop('disabled',true);
}
});
});
or inside the function you could do :-
$(this).prop('disabled',
$(this).closest('tr')
.find('#Status_Name')
.text() === 'cancelled');
If I understand you, something like this should work:
$('#Status_Name').on('keypress', function(e) { //I think that's how the XFor handlers format ids
$('button_to_disable').prop('disabled', this.value === 'Cancelled');
});
My application needs to do an HTTP post of a table with checkboxes . On the controller side I will need to traverse the table and perform certain operations for each row that was checked.
The things that I need to do are:
Identify whether a row is checked
Here is my code:
view :
#model IEnumerable<LinqToTwitter.User>
#{
ViewBag.Title = "Page d'accueil";
}
<h2>Twitter</h2>
<table>
<tr>
<td>
<input id="Checkbox1" type="checkbox" />
</td>
</tr>
#foreach (var tweet in Model)
{
<tr>
<td>
<input id="rowIDs" type="checkbox" />
</td>
<td>
<img alt="" src="#tweet.ProfileImageUrl" />
</td>
<td>
<strong>#tweet.Name</strong>
<br />
Friends: <strong>#tweet.FriendsCount</strong>
</td>
</tr>
}
</table>
controller :
{.....
string nextCursor = "-1";
List<LinqToTwitter.User> result = new List<LinqToTwitter.User>();
while (!string.IsNullOrEmpty(nextCursor) && nextCursor != "0")
{
var followers =
(from tweet in twitterCtx.User
where tweet.Type == UserType.Followers &&
tweet.ID == auth.UserId &&
tweet.Cursor == nextCursor
select tweet).ToList();
result.AddRange(followers);
nextCursor = followers[0].CursorMovement.Next;
}
return View(result);
}
Please help. Thanks.
If you want to post input tags to server, they must be in a form tag. Then your html must be something like this:
#model IEnumerable<LinqToTwitter.User>
#{
ViewBag.Title = "Page d'accueil";
}
<h2>
Twitter</h2>
#using (Html.BeginForm())
{
<table>
<tr>
<td>
<input id="Checkbox1" type="checkbox" />
</td>
</tr>
#foreach (var tweet in Model)
{
<tr>
<td>
<input id="#("chk" + #tweet.ID.ToString())" type="checkbox" name="#("chk" + #tweet.ID.ToString())" />
</td>
<td>
<img alt="" src="#tweet.ProfileImageUrl" />
</td>
<td>
<strong>#tweet.Name</strong>
<br />
Friends: <strong>#tweet.FriendsCount</strong>
</td>
</tr>
}
</table>
}
note how to define form tag by HtmlHelper and define of checkbox to have unique ID.
and your controller code like this:
Dictionary<int, bool> isChecked = new Dictionary<int, bool>();
foreach (LinqToTwitter.User item in twitterCtx.User)
{
if (Request.Form["chk" + item.ID.ToString()] != null && Request.Form["chk" + item.ID.ToString()] == "on")
isChecked.Add(item.ID, true);
else
isChecked.Add(item.ID, false);
}
now isChecked Dictionary is contain each item's Id and whether is check or not.