How to pass a table values to a controller? - c#

Brief Explanation:
I have a dynamic table in where I add Products that have ID,NAME,PRICE,COST and TOTAL.
With a drop-down list full of products when I click a button a product is added to the table
The table has inputs inside in order to set the quantity and the total based on the price of the product.
The thing is, when the table is done, I need to handle the table values in the controller to do some stuff in SQL.
I have read some other similar cases but I think none is like mine.
Example of my table with 1 product
<table id="tablaCompras" class="table table-striped table-responsive" cellpadding="0" cellspacing="0" name="tablaCompras">
<tbody>
<tr align="left">
<th scope="col">Número Artículo</th>
<th scope="col">Artículo</th>
<th scope="col">Cantidad</th>
<th scope="col">Costo Unitario</th>
<th scope="col">Total</th>
<th scope="col">Precio Unitario</th>
<th scope="col">Impresión</th>
<th scope="col">Eliminar</th>
</tr>
<tr id="0" align="left"><td>31</td><td width="100%">ANILLO DE PLATA 030269</td><td> <input type="text" id="txtCantidadTabla0" value="0.00" name="txtCantidadTabla" 0min="1" style="background: transparent; border:none; align:center; max-width:100px;" onblur="getTotal(txtCantidadTabla0.value ,txtCostoTabla0.value,0)" required=""></td>
<td> <input type="text" id="txtCostoTabla0" name="txtCostoTabla0" value="89.7" style="background: transparent; border:none; align:center; max-width:100px;" onblur="getTotal(txtCantidadTabla0.value ,txtCostoTabla0.value,0)" required=""> </td>
<td> <input id="txtTotalTabla0" type="text" style="background: transparent; border:none; align:center; max-width:100px;" readonly=""> </td>
<td> <input type="text" id="txtPrecioTabla0" name="txtPrecioTabla0" value="269.9" style="background: transparent; border:none; align:center; max-width:100px;" required=""></td>
<td> <img src="../Img/imprimir.png" style="width:30px; height:30px;"></td><td> <img src="../Img/borrar.png" onclick="deleteRow(0)" style="width:30px; height:30px;"></td>
</tr>
</tbody>
</table>
I have my table in a Html.BeginForm like this:
#using (Html.BeginForm("Prueba", "AltaCompra", FormMethod.Post))
{
}
In my controller I tried to receive it like this:
[HttpPost]
public ActionResult Prueba(FormCollection collection)
{
}
But Tables cannot be passed through to a formcollection.
Any clues of how can I handle the information of the table.

You need update your name for input with format name="#("txtCantidadTabla[" + #i + "]")", incase you add new row by javascript/jQuery you must add name with this format.
#for (var i = 0; i < 5; i++) // I assume the total product
{
<tr id="0" align="left">
<td><input type="hidden" name="productid" value="31" />31</td>
<td width="100%">ANILLO DE PLATA 030269</td>
<td> <input type="text" id="#("txtCantidadTabla[" + #i + "]")" value="0.00" name="#("txtCantidadTabla[" + #i + "]")" 0min="1" style="background: transparent; border:none; align:center; max-width:100px;" onblur="getTotal(txtCantidadTabla0.value ,txtCostoTabla0.value,0)" required=""></td>
<td> <input type="text" id="#("txtCantidadTabla[" + #i + "]")" name="#("txtCostoTabla[" + #i + "]")" value="89.7" style="background: transparent; border:none; align:center; max-width:100px;" onblur="getTotal(txtCantidadTabla0.value ,txtCostoTabla0.value,0)" required=""> </td>
<td> <input id="txtTotalTabla0" type="text" style="background: transparent; border:none; align:center; max-width:100px;" readonly=""> </td>
<td> <input type="text" id="#("txtCantidadTabla[" + #i + "]")" name="#("txtPrecioTabla[" + #i + "]")" value="269.9" style="background: transparent; border:none; align:center; max-width:100px;" required=""></td>
<td> <img src="../Img/imprimir.png" style="width:30px; height:30px;"></td>
<td> <img src="../Img/borrar.png" onclick="deleteRow(0)" style="width:30px; height:30px;"></td>
</tr>
}
And get data by FormCollection in controller as
[HttpPost]
public ActionResult Prueba(FormCollection collection)
{
for (var i = 0; i < 5; i++)
{
var txtCantidadTabla = collection["txtCantidadTabla[" + i + "]"];
var txtCostoTabla = collection["txtCostoTabla[" + i + "]"];
var txtPrecioTabla = collection["txtPrecioTabla[" + i + "]"];
// handle your logic here
}
return View();
}

Based on the id of the <tr> matching the last character of the name attribute for the input elements you probably need to modify your code to generate the name attribute to have array notation around the index value such as name="txtCostoTabla[0]" where the index of the row is the hard coded index if you want multiple values submitted in the form POST with the same name.
Otherwise as suggested in a previous comment handle the form submit with JavaScript and build an object to pass to the Controller by iterating the table rows.

Related

C# selenium find an element by text then click on checkbox

I want to search for example (UK) then click on checkbox that is in the same row
HTML (but tr can increase or decrease)
<tr class="ng-scope table-row-style">
<td class="ng-binding">US</td>
<td class="ng-binding">United States</td>
<td class="btn-td" style="padding: 0;">
<input type="checkbox" class="ng-pristine ng-untouched ng-valid ng-empty">
</td>
</tr>
<tr class="ng-scope table-row-style">
<td class="ng-binding">UK</td>
<td class="ng-binding">United Kingdom</td>
<td class="btn-td" style="padding: 0;">
<input type="checkbox" class="ng-pristine ng-untouched ng-valid ng-empty">
</td>
</tr>
<tr class="ng-scope table-row-style">
<td class="ng-binding">IN</td>
<td class="ng-binding">India</td>
<td class="btn-td" style="padding: 0;">
<input type="checkbox" class="ng-pristine ng-untouched ng-valid ng-empty">
</td>
</tr>
solved by
IList<IWebElement> tableRow = tableElement.FindElements(By.TagName("tr"));
IList<IWebElement> rowTD;
if (tableRow.Count > 0)
{
foreach (IWebElement row in tableRow)
{
rowTD = row.FindElements(By.TagName("td"));
if (rowTD[0].Text.Equals("UK"))
rowTD[2].Click();
}
}
You can find the parent tr element based on child td containing the desired text and then find the child input element as following:
//tr[.//td[contains(.,'UK')]]//input
The entire Selenium command finding and clicking this element could be
driver.FindElement(By.XPath("//tr[.//td[contains(.,'UK')]]//input")).Click();

Object reference not set to an instance of an object when posting files using HttpPostedFileBase[]

I am getting an error message - Object reference not set to an instance of an object. I believe that 'files' is empty - but not sure why. Could someone tell me why files would be empty?
Thanks!
View:
<form type="multipart/form-data" action="#Url.Action("AddImage", "HelpDesk")" method="post">
<table cellpadding="0" cellspacing="0" style="width: 100%">
<tr>
<td style="width: 105px"><br /></td>
<td> </td>
</tr>
<tr>
<td style="width: 105px; font-weight: bold">Attach File(s):</td>
<td> </td>
</tr>
<tr>
<td>
<input type="hidden" id="id" name="id" value=#item.ID>
<input type="hidden" id="requesttype" name="RequestType" value=#item.RequestType>
<input type="file" id="files" name="files" multiple>
</td>
</tr>
<tr>
<td>
<input type="submit" value="Add">
</td>
<td> </td>
</tr>
</table>
</form>
Controller:
public ActionResult AddImage(HelpdeskImage model, int id, string requesttype, HttpPostedFileBase[] files)
{
foreach (HttpPostedFileBase file in files)
{
var fileBytes = new byte[file.ContentLength];
file.InputStream.Read(fileBytes, 0, file.ContentLength);
hd.HelpdeskImages.Add(new HelpdeskImage
{
HelpdeskNum = id,
DocumentExt = Path.GetExtension(file.FileName),
Image = fileBytes,
DocumentName = System.IO.Path.GetFileName(file.FileName),
RequestType = requesttype,
Created = DateTime.Now,
}
);
hd.SaveChanges();
}
//}
return RedirectToAction("Details", new { id = id });
}
Modify your form tag to include enctype="multipart/form-data". Specifying this type is necessary when you have an input type="file".
<form enctype="multipart/form-data" action="#Url.Action("AddImage", "HelpDesk")" method="post">
...
</form>

Iterate through a table and get the value in asp.net core using jquery

I am trying to iterate through a table to get the input value. How can I do that ?
tried looping and iterating over the tr and class names. console.log showing nothing for the moment.
CSHTML
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.PositionDebit)
</td>
<td class="Debit">
<span>#item.Debits</span>
<input class="Debits" type="number" value="#item.Debits" />
</td>
<td class="CoefPonderation">
<span>#item.CoefficientDePonderation</span>
<input class="CoefPonderation" type="number" value="#item.CoefficientDePonderation" />
</td>
<td class="Jauge">
<span>#item.Jauge</span>
<input class="Jauge" type="number" value="#item.Jauge" />
</td>
</tr>
}
</tbody>
Javascript
The id of the table is tblDebit
$("#tblDebit tr").each(function () {
var debit = {};
debit.Debits = $(this).find(".Debits").html();
debit.CoefPonderation = $(this).find(".CoefPonderation").html();
debit.Jauge = $(this).find(".Jauge").html();
console.log(debit.Debits);
console.log(debit.CoefPonderation);
alert(debit.CoefPonderation);
debits.push(debit);
});
Hi you have some issues here:
First use .val() instead of .html().
you should use the class CoefPonderation in your td or input not both.
in your loop get each element and dont use this.
here is the javascript code:
$("#tblDebit").find("tbody").children("tr").each(function(index, element) {
let debits = [],
debit = {};
debit.Debits = $(element).find(".Debits").val();
debit.CoefPonderation = $(element).find(".CoefPonderation").children('input[type="number"]').val();
debit.Jauge = $(element).find(".Jauge").val();
// console.log(debit.Debits);
// console.log(debit.CoefPonderation);
console.log('row:' + $.trim($(element).find("td").first().text()) + ', debit:' + debit.Debits + ', ponderation:' + debit.CoefPonderation);
debits.push(debit);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="tblDebit" border="1">
<thead>
<th>row</th>
<th>Debits</th>
<th>Ponderation</th>
<th>Jauge</th>
</thead>
<tbody>
<tr>
<td>
1
</td>
<td class="Debit">
<span>item 1</span>
<input class="Debits" type="number" value="1" />
</td>
<td class="CoefPonderation">
<span>ponderation 1</span>
<input class="CoefPonderation" type="number" value="1" />
</td>
<td class="Jauge">
<span>Jauge 1</span>
<input class="Jauge" type="number" value="1" />
</td>
</tr>
<tr>
<td>
2
</td>
<td class="Debit">
<span>item 2</span>
<input class="Debits" type="number" value="2" />
</td>
<td class="CoefPonderation">
<span>ponderation 2</span>
<input class="CoefPonderation" type="number" value="2" />
</td>
<td class="Jauge">
<span>Jauge 2</span>
<input class="Jauge" type="number" value="2" />
</td>
</tr>
</tbody>
</table>
Hope it helps
Instead of html() use val()
debit.Debits = $(this).find(".Debits").val();
debit.CoefPonderation = $(this).find(".CoefPonderation").val();
debit.Jauge = $(this).find(".Jauge").val();

I cannot get the correct TD to display with angular

I am trying to get the td to display based on true/false values for Loan. Everything is solid until I hit this point, where it prints out both of the td's instead td corresponding to the value of true/false
<tbody>
<tr ng-repeat="dvd in dvds | filter: dvdFilter">
<td>{{dvd.Title}}</td>
<td>{{dvd.Rating.RatingName}}</td>
<td>{{dvd.MovieDirector}}</td>
<td>IMDb</td>
<td>
<button value={{dvd.DvdId}} class="btn btn-primary" id="btnDelete" ng-click="delete()">Delete</button>
</td>
<td ui-if{{dvd.Loan}}="true" style="color: green;">Available</td>
<td ui-if{{dvd.Loan}}="false" style="color: red;">Out on Loan</td>
</tr>
</tbody>
I believe your syntax is just a bit off. Try this on your td lines:
<td ng-if="dvd.Loan == 'true'" style="color: green;">Available</td>
<td ng-if="dvd.Loan == 'false'" style="color: red;">Out on Loan</td>
the answer ends up being
<td ng-if"dvd.Loan == true" style="color: red;">Out on Loan</td>
<td ng-if"dvd.Loan == false" style="color: green;">Available</td>

HtmlAgilityPack adding nodes to other nodes

I am using HtmlAgilityPack to parse my html. My main goal is add some div elements around table row elements. However there are also some more elements in the table row. I only want to wrap it with div elements when the font's style is a background color of lightgreen.
Here's an example of what my html looks like:
<tr>
<td style="padding-left: 40pt;"><font style="background-color: lightgreen" color="black">Tove</font></td>
<td style="padding-left: 40pt;"><font style="background-color: lightgreen" color="black">To</font></td>
</tr>
however my current code:
HtmlNode[] nodes = document.DocumentNode.SelectNodes("//tr[//td[//font[#style='background-color: lightgreen']]]").ToArray();
foreach (HtmlNode node in nodes)
{
node.InnerHtml = node.InnerHtml.Replace( node.InnerHtml,"<div class=\"select-me\">" +node.InnerHtml + "</div>");
}
produces this html:
<tr>
<div class="select-me">
<td style="padding-left: 25pt;"><font style="background-color: white" color="black"><to</font><font style="background-color: white" color="black">></font></td>
<td style="padding-left: 25pt;"><font style="background-color: white" color="black"><to</font><font style="background-color: white" color="black">></font></td>
</div>
</tr>
<tr>
<div class="select-me">
<td style="padding-left: 40pt;"><font style="background-color: lightgreen" color="black">Tove</font></td>
<td style="padding-left: 40pt;"><font style="background-color: lightgreen" color="black">To</font></td>
</div>
</tr>
<tr>
<div class="select-me">
<td style="padding-left: 25pt;"><font style="background-color: white" color="black"></to></font></td>
<td style="padding-left: 25pt;"><font style="background-color: white" color="black"></to></font></td>
</div>
</tr>
the div elements don't surround the tr elements and every tr has a div element, when only a tr element that has font element of background color lightgreen should contain a div element. If you look at the first tr element it has 4 font elements, instead of two. Ideally, my goal is to insert div elements around a tr element when its font's element background is lightgreen. I have looked at other posts, but I am still having trouble.
Correct html should like:
<div class="select-me">
<tr>
<td style="padding-left: 25pt;"><font style="background-color: lightgreen" color="black">hello</font></td>
<td style="padding-left: 25pt;"><font style="background-color: lightgreen" color="black">goodbye</font></td>
</tr>
</div>
for (var i = 0; i < nodes.Length; i++ )
{
var node = nodes[i];
node = HtmlNode.CreateNode(node.OuterHtml.Replace(node.OuterHtml, "<div class=\"select-me\">" + node.OuterHtml + "</div>"));
}

Categories