EDIT: Basically want to change the current method of adding more than one of the same product from adding them individually to the cart to when one has been added you can just input how many you want.
Hi guys so currently in my system the quantity of an item added to the cart is updated by the user clicking to continue shopping and going back and selecting a new item each time they wish to add it. I would like for this to be done through either an editor or text box so they can select the quantity they want without having to go back to view the product like 3 times.
Add method (Shopping Cart Controller)
public ActionResult AddToCart(int id)
{
var addedProduct = db.Products.Single(product => product.ID == id);
var cart = ShoppingCart.GetCart(this.HttpContext);
cart.AddToCart(addedProduct);
return RedirectToAction("Index");
}
Add method (Shopping Cart Model)
public void AddToCart(Product product)
{
var cartItem = db.Carts.SingleOrDefault(c => c.CartId == ShoppingCartId && c.ProductId == product.ID);
if (cartItem == null)
{
cartItem = new Cart
{
ProductId = product.ID,
CartId = ShoppingCartId,
Count = 1,
DateCreated = DateTime.Now
};
db.Carts.Add(cartItem);
}
else
{
cartItem.Count++;
}
db.SaveChanges();
}
shopping cart view model
public class ShoppingCartViewModel
{
public List<Cart> CartItems { get; set; }
public decimal CartTotal { get; set; }
}
}
Shopping Cart View
#{
ViewBag.Title = "Store Checkout";
CultureInfo us = new CultureInfo("en-GB");
}
<h3 class="text-center">
<span><img src="~/Content/Images/shoping_cart.png" />Your shopping cart:</span>
</h3>
<div id="update-message" class="text-info">
</div>
#if (Model.CartItems.Count == 0)
{
<a class="btn-danger" href="~/Products/Index">Your shopping cart is empty, continue shopping---></a>
}
else
{
<table class="table-responsive table-bordered table-striped">
<tr>
<th>
Product Name
</th>
<th>
Price (each)
</th>
<th>
Quantity
</th>
<th>Sub-total</th>
<th></th>
</tr>
#foreach (var item in Model.CartItems)
{
<tr id="row-#item.ProductId">
<td>
#Html.ActionLink(item.Product.Name, "Details", "Products", new { id = item.ProductId }, null)
</td>
<td>
#item.Product.Price
</td>
<td id="item-count-#item.ProductId">
#item.Count
</td>
<td>
#((item.Product.Price * item.Count).ToString("c", us))
</td>
<td>
<a href="" class="RemoveLink" data-id="#item.ProductId">
Remove from cart
</a>
</td>
</tr>
}
<tr>
<td>
Total
</td>
<td></td>
<td></td>
<td id="cart-total" class="text-success">
<b>#Model.CartTotal.ToString("C", us)</b>
</td>
</tr>
</table>
<p class="button">
<a>#Html.ActionLink("Continue Shopping", "Index", "Products")</a>
</p>
<p class="button">
#Html.ActionLink("Click and Collect Order>> ", "AddressAndPayment", "Checkout") #Html.ActionLink("Checkout With Braintree>> ", "AddressAndPaymentBraintree", "Checkout")
</p>
}
Any Help to solving this would be much appreciated.
This is a basic form submission
#using(Html.BeginForm("UpdateQuantity", "ShoppingCart", FormMethod.Post))
{
<input name="cartId" value="#cart.Id" type="hidden" />
<input name="productId" value="#product.Id" type="hidden" />
<input name="quantity" type="text" />
<button type="submit">Update</button>
}
The update action
[HttpPost]
public ActionResult UpdateQuantity(int cartId, int productId, int quantity)
{
var cart = db.Carts.FirstOrDefault(c => c.CartId == cartId);
cart.Count = quantity;
db.SaveChanges();
return RedirectToAction("MyCart", routeValues: new { cartId = cartId });
}
[HttpGet]
public ActionResult MyCart(int cartId)
{
var cart = db.Carts.FirstOrDefault(c = c.CartId == cartId);
return View(cart);
}
Hi thanks for the answer Jasen but I found a simplier fix that serves my purpose. basically created a new row in my shopping cart table and added this to it #Html.ActionLink("Add Another?", "AddToCart", "ShoppingCart", new { id = item.ProductId }, new { #class = "btn btn-info" }) thanks for your answer though it might help others but this worked for me.
Related
Checkbox does not retains checked status while using pagination. When moving to another page, why checkbox unchecks.
My pagination is working fine. The only issue is to maintain checkbox checked status.
Used ViewBag to store the current filter state but no luck.
No idea where to go and change the code to make it work. Can anyone put some lights on it.
Controller
Public async Task<IActionResult> Index(bool searchText, bool currentFilter, int? page)
{
int selectedPage = page ?? 1;
int bypassCount = (selectedPage - 1) * _pagingOptions.PageSize;
if (searchText != false)
{
page = 1;
}
else
{
searchText = currentFilter;
}
ViewBag.CurrentFilter = searchText;
}
index
<form asp-action="Index" method="get">
<input type="checkbox" asp-for="searchText" class="form-control" />
<div class="col-md-12">
<button class="btn btn-primary" type="submit">Search</button>
</div>
</form>
<table class="table">
<thead>
<tr >
<th>Message Id</th>
<th>Status</th>
<th>Resent</th>
<th>Resent Date</th>
<th>Created Date</th>
</tr>
</thead>
<tbody>
#if (Model.Items.TotalItemCount > 0)
{
#foreach (var item in Model.Items.ToList())
{
<td>#Html.DisplayFor(modelItem => item.MessageId)</td>
<td>#Html.DisplayFor(modelItem => item.Status)</td>
<td>#Html.DisplayFor(modelItem => resentString)</td>
<td>#Html.DisplayFor(modelItem => resentDateString)</td>
<td>#Html.DisplayFor(modelItem => createdDateString)</td>
</tr>
}
}
</tbody>
</table>
</div>
#if (Model.Items.PageCount > 1)
{
#Html.PagedListPager(Model.Items, page => Url.Action("Index", new { page = page, currentFilter = ViewBag.CurrentFilter}),
new PagedListRenderOptions
{
UlElementClasses = new string[] { "pagination", "justify-content-left" },
LiElementClasses = new string[] { "page-item" },
PageClasses = new string[] { "page-link" },
LinkToPreviousPageFormat = "Previous",
LinkToNextPageFormat = "Next",
DisplayEllipsesWhenNotShowingAllPageNumbers = true,
DisplayLinkToPreviousPage = PagedListDisplayMode.Always,
DisplayLinkToNextPage = PagedListDisplayMode.Always
})
}
To check the checkbox based on specific value , for example , based on CurrentFilter , you can try with below codes :
#{
int status = ViewBag.CurrentFilter ? 1 : 0;
}
<input type="checkbox" checked="#(1 == status)" class="form-control" />
Reference : https://www.learnrazorpages.com/razor-pages/forms/checkboxes
Just wanted to ask if there's something I missed here.
I have two tables that I joined together in my controller
using .NET MVC btw
anyway, here's my controller:
namespace Review.Controllers
{
public class ReviewController : Controller
{
ReviewContext db = new ReviewContext();
ReviewItemsContext db2 = new ReviewItemsContext();
MainDataModel db3 = new MainDataModel();
List<UAR_Review> uar_review = new List<UAR_Review>();
List<UAR_ReviewItems> uar_reviewitems = new List<UAR_ReviewItems>();
public ActionResult Index(int? page) {
ViewBag.AccList = (from r in db2.UAR_ReviewItems
select r.Account).Distinct();
/*var entities = from s in db2.UAR_ReviewItems
orderby s.Account
select s;*/
var entities = from s in uar_review
join st in uar_reviewitems on s.ID equals st.ReviewID into st2
from st in st2.DefaultIfEmpty()
select new MainDataModel { UAR_Review = s, UAR_ReviewItems = st };
int pageSize = 15;
int pageNumber = (page ?? 1);
return View(entities.ToPagedList(pageNumber, pageSize));
}
}
}
and here's my view:
#model PagedList.IPagedList<Review.Models.MainDataModel>
#using PagedList.Mvc;
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />
#{
ViewBag.Title = "Index";
}
#using (Html.BeginForm("Index", "Review", FormMethod.Get))
{
<h2>Index</h2>
#section NavBar{
<h3>Period: 2 of 2018</h3>
#Html.DropDownList("userAccount", new SelectList(ViewBag.AccList), "Select Account to Filter")
<input type="submit" value="Search" />
}
#section MiddleSection{
<table class="table">
<tr>
<th>
<span class="arrow-link contrast-large light-blue">#Html.DisplayName("Name")</span>
</th>
<th>
<span class="arrow-link contrast-large light-blue">#Html.DisplayName("Role")</span>
</th>
<th>
<span class="arrow-link contrast-large light-blue">#Html.DisplayName("Action")</span>
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
<span class="font-gotham-narrow">#item.UAR_Review.DisplayName</span>
</td>
<td>
<span class="font-gotham-narrow">#item.UAR_ReviewItems.Role</span>
</td>
<td>
#Html.HiddenFor(modelItem => item.UAR_ReviewItems.Response)
<span class="font-gotham-narrow">
#Html.RadioButton("Response", "Retain")#Html.Label("Retain")
</span>
<span class="font-gotham-narrow">
#Html.RadioButton("Response", "Remove")#Html.Label("Remove")
</span>
</td>
</tr>
}
</table>
<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 }))
}
}
}
The problem is, when I run it there is nothing being displayed in the Site.here's the page.
I just wanted to ask if there's anything I missed.
Also, please disregard the dropdownlist on the left side, I've been planning to use it to sort the shown elements in the page by AccountType(This is stored in my UAR_ReviewItems table). For now, I'm just trying to figure out what's wrong here and why there are no elements being displayed.
Your screen grab does say the PageCount is 0.
Your Model in empty. Check your queries.
In my MVC application, I have specified two conditions based on the Model.Count to display the values in View.
View
#model IEnumerable<SampleECommerce.Models.DetailsModel>
#using (Html.BeginForm("Details", "Grid", new { UserID = Request.QueryString["UserID"], partnerid = Request.QueryString["Partnerid"] }, FormMethod.Post))
{
if (Model.Count() == 0)
{
#foreach (var item in Model)
{
<table>
<tr>
<td>
#Html.DisplayNameFor(model => model.FirstName)
<input id="FirstName" type="text" class="TextBoxBorder" name="FirstName" value="#item.FirstName" /> // When the Model count is zero, the label and textbox is not displayed.
</td>
</tr>
</table>
}
else
{
#foreach (var item in Model)
{
<table>
<tr>
<td>
#Html.DisplayNameFor(model => model.FirstName)
<input id="MFirstName" type="text" class="TextBoxBorder" name="FirstName" value="#item.FirstName" />
</td>
</tr>
</table>
}
Controller
public ActionResult Details()
{
string userid = Request.QueryString["UserID"];
string partnerid = Request.QueryString["Partnerid"];
con.Open();
SqlCommand cmd = new SqlCommand("select FirstName from Details where UserID = +userid+", con);
SqlDataReader dr = cmd.ExecuteReader();
List<DetailsModel> objmodel = new List<DetailsModel>();
while (dr.Read())
{
objmodel.Add(new DetailsModel()
{
FirstName = dr["First Name"].ToString(),
});
}
dr.Close();
return View(objmodel);
}
When the Model.Count is zero, the label and textbox are not displayed.
I am trying to insert new value to textbox when the model.count is zero based on the userid
I tried to bind the textbox to model all the ways specified in the Link.
1. #Html.TextBoxFor(model => model.FirstName)
Error in FirstName stating "System.Collections.Generic.IEnumerable doesnot find definition for FirstName or no extension method "
2. #Html.TextBox(model=>model.FirstName)
"Error stating Cannot convert Lamba expression to string type"
How to bind and display the textbox value to the model when the model.count is zero.
Any suggestions ??
when the Model.Count is 0, foreach does nothing .
#model IEnumerable<SampleECommerce.Models.DetailsModel>
#using (Html.BeginForm("Details", "Grid", new { UserID = Request.QueryString["UserID"], partnerid = Request.QueryString["Partnerid"] }, FormMethod.Post))
{
<table>
if (Model.Count() == 0)
{
<tr>
<td>
#Html.DisplayNameFor(model => model.FirstName)
<input id="FirstName" type="text" class="TextBoxBorder" name="FirstName" /> // When the Model count is zero, the label and textbox is not displayed.
</td>
</tr>
}
else
{
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayNameFor(model => model.FirstName)
<input id="MFirstName" type="text" class="TextBoxBorder" name="FirstName" value="#item.FirstName" />
</td>
</tr>
}
}
<tr>
<td>
<input type="submit" value="submit" />
</td>
</tr>
</table>
}
I am currently writing a simple MVC 3 application that displays a list of items and allows the user to filter the items (on the same page). The user can then click on an item and will be redirected to a details page.
The problem I have is that when the user clicks 'back to list' the search criteria is lost and so is the current page (search results are paged).
I am new to MVC and cannot seem to figure out how this should be done.
Controller
....
public ActionResult Index(PacketSearch search)
{
const int pageSize = 20;
var allPackets = this.repository.GetAllPackets().Where(p => (string.IsNullOrEmpty(search.FromIp)) || p.FromIp == search.FromIp);
var pagedPackets = new PaginatedList<RawPacket>(allPackets, search.Page ?? 0, pageSize);
search.SearchResults = pagedPackets;
return View(search);
}
public ActionResult Details(int id)
{
var packet = this.repository.GetPacket(id);
return View(packet);
}
Main page
....
#if (Model.SearchResults != null && Model.SearchResults.Count > 0)
{
<table>
<tr>
<th>
Timestamp
</th>
<th>
From IP
</th>
</tr>
#foreach (var item in Model.SearchResults) {
<tr>
<td>
#Html.ActionLink(item.TimestampString, "Details", "Packets", new { id = item.Id }, null)
</td>
<td>
#Html.DisplayFor(modelItem => item.FromIp)
</td>
</tr>
}
</table>
}
<br />
#if (Model.SearchResults.HasPreviousPage)
{
#Html.RouteLink("<<<", "Packets", new { page = (Model.SearchResults.PageIndex - 1) })
}
Page #(Model.SearchResults.PageIndex + 1) of #Model.SearchResults.TotalPages
#if (Model.SearchResults.HasNextPage)
{
#Html.RouteLink(">>>", "Packets", new { page = (Model.SearchResults.PageIndex + 1) })
}
Details Page
<h2>Packet Details</h2>
<fieldset>
<legend>RawPacket</legend>
<div class="display-label">Timestamp</div>
<div class="display-field">
#Html.DisplayFor(model => model.TimestampString)
</div>
<div class="display-label">FromIp</div>
<div class="display-field">
#Html.DisplayFor(model => model.FromIp)
</div>
</fieldset>
<p>
#Html.ActionLink("Back to List", "Index")
</p>
Any help would be much appreciated, thanks.
You must persist the input somewhere and the best place is url(because it can be cached and remembered by user).
Define another Action in controller which will do the main job of searching and send the search parameters through a query string to it.
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.