Reputation: 93
I have a table whose values are looped with my product list and I have a textbox for 'Quantity' and a button for 'Add to Cart'. I am trying to do when I click on 'Add to Cart' button, it will check the Quantity value if it has value or not then the 'Quantity' textbox will get disabled for that specific row only.
Product.cshtml
<table id ="productList" class="table table-dark">
<tr>
<th>Product ID</th>
<th>Title</th>
<th>Description</th>
<th>Quantity</th>
<th>Add to cart</th>
</tr>
@foreach (var item in Model)
{
<tr class="active">
<td>@item.Id</td>
<td>@item.Title</td>
<td>@item.Description</td>
<td>@Html.TextBox("Quantity", "0", new { @class = "form-control" })</td>
<td><button class="btn btn-default pull-left" onclick="disableText(Quantity);" id="btn-addToCart">Add To Cart</button></td>
</tr>
}
</table>
javascript
function disableText(QtyVal) {
if(QtyVal.value == '')
{
document.getElementById("Quantity").value = 1;
}
}
Currently the output of my project is everytime I click any submit button, it will always update the first row (which is incorrect).
The goal is it will update the Quantity and disable it for that specific row
Upvotes: 1
Views: 2440
Reputation: 24957
Your problem lies in this button definition:
<button class="btn btn-default pull-left" onclick="disableText(Quantity);" id="btn-addToCart">Add To Cart</button>
The foreach
loop generates duplicate id
attribute values for all buttons, which builds invalid HTML and causing undesired behavior. Since your table also contains <input>
tag, you should use for
loop instead of foreach
and put distinct class name to the button, e.g. buttonadd
:
<!-- assumed that @model List<Product> is used -->
<table id ="productList" class="table table-dark">
<tr>
<th>Product ID</th>
<th>Title</th>
<th>Description</th>
<th>Quantity</th>
<th>Add to cart</th>
</tr>
@for (int i = 0; i < Model.Count; i++)
{
<tr class="active">
<td>@Model[i].Id</td>
<td>@Model[i].Title</td>
<td>@Model[i].Description</td>
<td>@Html.TextBox("Quantity", "0", new { @class = "form-control" })</td>
<td><button type="button" class="btn btn-default pull-left buttonadd">Add To Cart</button></td>
</tr>
}
</table>
Then you can reference buttonadd
class as selector to find out which row the button contained, and setting <input>
state to readonly
(not disabled
because you want to send quantity values on form submit; all inputs with disabled
attribute are not included during submit) as in example below:
$(document).on('click', '#productList .buttonadd', function () {
var row = $(this).closest('tr');
// find quantity text box in the same row as clicked button
var qty = row.find('input');
// set quantity value and prevent user input
qty.val(parseInt(qty.val()) + 1);
qty.attr('readonly', 'readonly');
});
Note: If you want to use strongly-typed helper, use @Html.TextBoxFor
:
@Html.TextBoxFor(m => m[i].Quantity, new { @class = "form-control" })
Live example: .NET Fiddle
Upvotes: 2
Reputation: 34196
Use a partial view, save some headache.
<table id ="productList" class="table table-dark">
<tr>
<th>Product ID</th>
<th>Title</th>
<th>Description</th>
<th>Quantity</th>
<th>Add to cart</th>
</tr>
@foreach (var item in Model)
{
@Html.Partial("~/Views/_OrderRowPartial.cshtml", item)
}
</table>
_OrderRowPartial.cshtml:
@model item
<tr class="active">
<td>@item.Id</td>
<td>@item.Title</td>
<td>@item.Description</td>
<td>@Html.TextBoxFor(m => m.Quantity, new { @class = "form-control quantity" })</td>
<td><button class="btn btn-default pull-left" onclick="disableText();">Add To Cart</button></td>
</tr>
Javascript:
function disableText(t, el) {
var qty = el.parentElement.previousElementSibling.getElementsByTagName('input')[0];
mytd.style.border = "1px solid #00FF00";
console.log(qty.value);
if (qty.value == '') {
qty.value = 1;
}
}
Here is an example where I set borders on stuff to make it obvious what is going on. Unclear if you want to disable input or button so I did both.
function disableText(t, el) {
el.style.border = "2px solid #FF0000";
var mytd = el.parentElement;
mytd.style.border = "1px solid #00FF00";
var mytr = mytd.parentElement;
var qtytd = mytd.previousElementSibling;
var qty = qtytd.getElementsByTagName('input')[0];
qtytd.style.border = "2px solid orange";
qty.style.border = "2px solid cyan";
console.log(qty.value);
if (qty.value == '') {
qty.value = 1;
}
// disable button
el.setAttribute("disabled", "disabled");
qty.setAttribute("disabled", "disabled");
}
<table id="productList" class="table table-dark">
<tr>
<th>Product ID</th>
<th>Title</th>
<th>Description</th>
<th>Quantity</th>
<th>Add to cart</th>
</tr>
<tr class="active">
<td>1234d</td>
<td>Cherry Pie</td>
<td>Gooey cherry pie</td>
<td><input type="text" class="form-control quantity" value="2" .>
<td><button class="btn btn-default pull-left" onclick="disableText('',this);">Add To Cart</button></td>
</tr>
<tr class="active">
<td>1234hd</td>
<td>Hot Dog</td>
<td>Dog, With mustard</td>
<td><input type="text" class="form-control quantity" /></td>
<td><button class="btn btn-default pull-left" onclick="disableText('',this);">Add To Cart</button></td>
</tr>
</table>
Upvotes: 0
Reputation: 177
You just need to add bellow code at button click event
(this).prev('input').attr("disabled", "disabled")
Upvotes: 0
Reputation: 1734
Since all of your textboxes have the same Id you cannot specify which one you are trying to update in your js. Try giving a unique ID to your TextBox then when you getElementById("UniqueID") you can ensure you are selecting the correct text box.
Upvotes: 0