ASP How to get a value from HTML column - html

I have an ASP page which displays rows of data in an HTML table, after a query to an SQL database. The number of returned rows can vary. I want to add a function so that when i click on a button, I fire off a query to the SQL server database to update a column in that particular row. To do that i will use the primary key from my result set.
The part I am having difficulty with is getting the proper rows ID. What I have wrote so far returns the same ID every time regardless of which row i click on. Sample code below.
<table>
<tr>
<td class="bold" colspan="9"><%=vHeading%></td>
</tr>
<tr>
<td class="tablehead">Id</td>
<td class="tablehead">WhenPosted</td>
<td class="tablehead">WhenCreated</td>
<td class="tablehead">WhenUpdated</td>
<td class="tablehead">Source</td>
<td></td>
</tr>
<%
DO WHILE NOT stRs.eof
i = i + 1
%>
<tr>
<td id="pId<%=i%>" class="tablecell"><%=stRs.fields("Id")%></td>
<td class="tablecell"><%=stRs.fields("WhenPosted")%></td>
<td class="tablecell"><%=stRs.fields("WhenCreated")%></td>
<td class="tablecell"><%=stRs.fields("WhenUpdated")%></td>
<td class="tablecell"><%=stRs.fields("Source")%></td>
<td id=<%=i%>><input type="button" value="Post" onclick="post();" /></td>
</tr>
<%
stRs.MoveNext
LOOP
%>
</table>
<script text="text/javascript">
function post() {
var pId = document.getElementById("pId").innerHTML;
alert(pId);
}
</script>
So i loop through my result set creating rows. For examples-sake, row one will contain ID 1. Row 2 will have ID 2 etc.
If I click on my button which fires off the post method, the alert shows ID 1 every time, no matter the row i click on. I guessed its because i was originally assigning the same ID to the column for each row. I now use a counter variable and assign it to the ID which is creating unique ID's for the columns now, but I'm not sure how to call the function and use the correct ID. Any pointers are much appreciated!

You have to pass I to the function:
<input type="button" value="Post" onclick="post(<%=i%>);" />
then
<script text="text/javascript">
function post(i) {
var pId = document.getElementById("pId"+i).innerHTML;
alert(pId);
}
</script>

Related

Posting row model data from a table within a form (no JS)

I ran into an almost identical issue before and posted a question about it here: Posting data of a single table row when table is in one form We were able to solve it but it felt pretty hacky. To summarize that post, I was attempting to use AJAX and JS to POST values from a table row to a controller. The problem was that every row would be serialized within the form. To solve this, I serialized only the row I needed.
This time I am running into the same issue, the only difference being that I'm not using AJAX and am submitting the model data from the table row directly to the controller action.
I tried to use both the foreach and for loops to generate table rows.
The foreach loop always POSTs the first row in the table, even if I click submit button on the second row.
The for loop doesn't POST anything, or at least I get all null values in my controller action's "shipment" parameter.
I also tried to encase the row in a form, but HTML does not allow to have a <form> in <tbody>.
What I want is to be be able to POST a single row (generated by looping through a list for models) directly to the "UpdateShipment" controller action. All of this without using AJAX.
HTML code:
#model OrderTrackingContract.SalesOrder
#foreach (var lineItem in Model.LineItems)
{
<table class="lineItemTables">
//line items table
</table>
#if (lineItem.Shipments.Count > 0)
{
<form method="post">
<table class="table shipmentTable">
<thead>
<tr>
<th>
ShipmentID
</th>
<th>
Qty Shipped
</th>
<th>
Actions
</th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < lineItem.Shipments.Count; i++)
{
<tr>
<td>
<input class="shipmentID" asp-for="#lineItem.Shipments[i].ShipmentID" />
</td>
<td>
<input class="qtyShipped" asp-for="#lineItem.Shipments[i].QtyShipped" value="#lineItem.Shipments[i].QtyShipped" min="1" max="999" />
</td>
<td>
<input class="updateButton" type="submit" value="Update" asp-action="UpdateShipment" asp-controller="Shipments" />
<input class="deleteButton" type="submit" value="Delete" asp-route-shipmentID="#lineItem.Shipments[i].ShipmentID" asp-action="DeleteShipment" asp-controller="Shipments" />
</td>
</tr>
}
</tbody>
</table>
</form>
}
}
Controller action:
[HttpPost]
public IActionResult UpdateShipment(Shipment shipment)
{
_orderTrackingService.UpdateShipmentByID(shipment.ShipmentID, shipment.QtyShipped);
return NoContent();
}
EDIT: I used fiddler and I'm starting to understand what's going on. Both for and foreach loop submit the whole form because the whole table is in it.
Using a for loop I am forced to write asp-for="#lineItem.Shipments[i].ShipmentID", which means the controller must accept a parameter of LineItem lineItem.
Using foreach loop I am able to write asp-for="#shipment.ShipmentID, but because the generated attributes of the <input> are identical, the 'Shipment shipment' parameter binds to the first values POSTed.
What I want is to be be able to POST a single row (generated by looping through a list for models) directly to the "UpdateShipment" controller action. All of this without using AJAX.
To achieve above requirement, you can try to generate <form> and <table> for each Shipment item, like below.
#foreach (var lineItem in Model.LineItems)
{
<table class="table shipmentTable">
<thead>
<tr>
<th>
ShipmentID
</th>
<th>
Qty Shipped
</th>
<th>
Actions
</th>
</tr>
</thead>
</table>
#if (lineItem.Shipments.Count > 0)
{
foreach (var Shipment in lineItem.Shipments)
{
<form method="post">
<table class="table shipmentTable">
<tbody>
<tr>
<td>
<input class="shipmentID" asp-for="#Shipment.ShipmentID" />
</td>
<td>
<input class="qtyShipped" asp-for="#Shipment.QtyShipped" value="#Shipment.QtyShipped" min="1" max="999" />
</td>
<td>
<input class="updateButton" type="submit" value="Update" asp-action="UpdateShipment" asp-controller="Shipments" />
<input class="deleteButton" type="submit" value="Delete" asp-route-shipmentID="#Shipment.ShipmentID" asp-action="DeleteShipment" asp-controller="Shipments" />
</td>
</tr>
</tbody>
</table>
</form>
}
}
}
Test Result

Angular JS-Storing the row wise table values into the database

I have this situation: I need to bring-up a table structure into a HTML page.One of the columns in this table has to be brought from a table stored in the database.This column value along with two check boxes values needs to be stored in a database and next time these stored values should be brought in ,next time we open that page
HTML code:
<label class="col-md-3" for="Documents">Test:</label>
<div class="col-md-8" ng-controller="checklistController" ng-init='populateChecklist()'>
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Not Required</th>
<th>Completed</th>
<th>Link</th>
</tr>
</thead>
<tbody>
<tr ng-repeat = "x in list">
<td>{{x.name}}</td>
<td><input type="checkbox" ng-model='notRequiredCheckList' ng-disabled="completedCheckList" ng-disabled="linkForCheckList"/></td>
<td><input type="checkbox" ng-disabled="notRequiredCheckList" ng-model="completedCheckList" /></td>
<td><input type="text" ng-model="linkForCheckList" size="30" ng-disabled="notRequiredCheckList"/></td>
</tr>
</tbody>
</table>
<button ng-click="Save()">Save</button>
</div>
<div>
Javascript code:
app.controller("checklistController",function($scope,$http){
$scope.populateChecklist = function(a){
$http.get("commonAppGet.jsp?sqlStr=select name from test where val="+a+").then(function(resp){
$scope.list = resp.data;
});
}
});
Here I am getting name from a table and populating the first column when the page is getting loaded.Now along with these names ,I have two checkboxes along with a text box.I have added few validations.Now my challenge is,how to store these values row wise into a new table in the database and load these stored values next time.
Could someone help me?

Angular UI-Bootstrap typeahead in table

Simple question really, but how can I setup the typeahead to work in a table that works off of a different table than my typeahead?
For Example, I have a foreign key in a table and I want to let the users select this key based on the respective NAME value in the foreign key's primary table.
Code Example:
<table class="table table-bordered table-hover table-striped rwd-table" id="page-wrap">
<thead>
<tr>
<th>Primary ID</th>
<th>Foreign Key (As Name)</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="p in PrimaryTable" id="display">
<td data-th="ID">{{p.PrimaryID}}</td>
<td>
<input id="ForeignKeyName"
type="text"
ng-model="p.ForeignKeyID"
uib-typeahead="f.ForeignKeyID as f.ForeignKeyName for f in ForeignKeyTable | filter:$viewValue"
class="form-control">
</td>
</tr>
</tbody>
With this example, I would want the users to see the "Foreign Key (As Name)" As the Name value instead of the ID value. The trick is that I also want the underlying value to be the ID and have it mapped to match the original value, as notified by the ng-model.
UPDATE: Another question I had that was in line with the previous one is how do I setup my ng-model to show the ForeignKeyTable.ForeignKeyName in place of the PrimaryTable.ForeignKeyID?
This would be similar ( I imagine) to how the uib-typeahead matches the ForeignKeyTable.ForeignKeyID and ForeignKeyTable.ForeignKeyName but with the two seperate tables?
What I would desire is to be able to put ng-model: PrimaryTable.ForeignKeyID as ForeignKeyTable.ForeignKeyName
First thing would be updating PrimaryKeyTable rows every time user selects value in typeahead. You'll have to catch selected item and manually assign its ForeignKeyId value to the row of PrimaryTable.
The way to do it is to add typeahead-on-select directive to your typeahead and bind it to the function that assigns the values for you.
It would look like this:
HTML
<tr ng-repeat="p in PrimaryTable" id="display">
<td data-th="ID">{{p.PrimaryID}}</td>
<td>
<input id="ForeignKeyName"
type="text"
ng-model="selectedItem" <!-- could be anything really for we will not use it here -->
uib-typeahead="f.ForeignKeyID as f.ForeignKeyName for f in ForeignKeyTable | filter:$viewValue"
typeahead-on-select="onSelect($item, $model, $label, p)"
class="form-control">
</td>
</tr>
Inside your controller
$scope.onSelect = function($item, $model, $label, primaryKeyTableRow) {
primaryKeyTableRow.ForeignKeyId = $item.ForeignKeyId;
}
Next step is to display name property value of ForeignKeyTable row that corresponds to ForeignKeyId from PrimaryKeyTable in each row. Since we have to filter ForeignKeyTable to find suitable item it would be a good idea to put that logic inside the controller. For there are multiple rows in which we want to display corresponding name, we'll have to filter the ForeignKeyTable for each row separately. This is where ng-controller for ng-repeat comes in handy. What we'll do is bind new controller for each table row generated by ng-repeat and put some logic inside that controller. In HTML it would look like this:
<tr ng-repeat="p in primaryKeyTable" ng-controller="itemController">
<!-- ... -->
</tr>
And we'll have to define new controller in JS file:
app.controller('itemController', function() {
// ...
});
Now we can have separate logic for each row in the table. So that's a place to filter ForeignKeyTable to find corresponding item and display it's name.
Since whole code is kind of big I've put it in the plunker:
http://plnkr.co/edit/xccgnpxoPHg6vhXWPwZn?p=preview
See what you can do with it.

How to use xpath to select a value in a drop down list located in a particular row?

I am testing a page using selenium web driver. I have rows of data that represent 'requests', and in the last column of each of those rows the user can click a drop down list (with the option to either approve or reject) element that allows them to 'approve' or 'reject' the request.
I need to be able to select the approve option on the drop down list of a row whose 'Name' column is equal to a variable (in this instance say the variable is 'John').
In this test the user will be approving 'John's' request by selecting approve. How do I use xpath to ensure I am selecting the correct drop down element for the right person (right row)? Will I need to include a select element within an xpath somehow?
An example of the select element method to select a drop down element:
new SelectElement(this.Driver.FindElement(By.Name("orm")).FindElement(By.Name("Tutors"))).SelectByText(tutorName);
<form name="RequestsForm" action="SubmitRequest.aspx" method="POST">
<h2 class="blacktext" align="center">Course approvals</h2>
<table class="cooltable" width="90%" border="0" cellspacing="1" cellpadding="1">
<tbody>
<tr>
<td class="heading">
<b>Name</b>
</td>
<td class="heading">
<b>Request Date</b>
</td>
<td class="heading">
<b>Approved</b>
</td>
</tr>
<tr>
<td>
John
<input id="T1" type="text" value="888" name="T1">
</td>
<td>1/3/2015</td>
<td>
<select id="D1" class="selecttext" size="1" name="D1">
<option>?</option>
<option value="Approved">Approved</option>
<option>Rejected</option>
</select>
</td>
</tr>
</tbody>
</table>
Using XPath, this gets the position where the Name column is in your table:
count(//table[#class='cooltable']/tbody/tr[1]/td[b = 'Name']/preceding-sibling::td)+1
You can use that position to get the corresponding table cell in the other columns. This selects the corresponding td in the second row (where the ... represent the expression above):
//table[#class='cooltable']/tbody/tr[2]/td[count( ... )+1]
Appending /text() will extract the text (with spaces). Using normalize-space() will trim the text so you can compare it with John:
normalize-space(//table[#class='cooltable']/tbody/tr[2]/td[count( ... )+1]/text()) = 'John'
To select only the tr which contains John in the Name column, you leave only the td in the predicate. Now it returns a node-set of all tr which match the predicate text = John:
//table[#class='cooltable']/tbody/tr[normalize-space(td[count( ... )+1]/text()) = 'John']
Finally, if you append //select/option[#value='Approved'] to that expression, you will select the option with the Approved attribute in the context of that tr. Here is the full XPath expression:
//table[#class='cooltable']/tbody/tr[normalize-space(td[count(//table[#class='cooltable']/tbody/tr[1]/td[b = 'Name']/preceding-sibling::td)+1]/text()) = 'John']//select/option[#value='Approved']

Cycle through input fields

I have a table which I'm populating with some data I get from a database query
Table example
<tr ng-repeat="row in reservasTable">
<td> {{row.L}} </td>
<td> {{row.number}} </td>
<td> {{row.line}} </td>
<td> {{row.cod_art}} </td>
<td> {{row.creation_date}} </td>
<td> {{row.deadline}} </td>
<td> {{row.qtt_ordered}} </td>
<td> {{row.qtt_delivered}} </td>
<td> {{row.ocor}} </td>
<td> <input type="text" id="qttField" ng-model-onblur ng-model="qtt" ui-keypress="{13:'setQtt($event)'}">
</tr>
The only field I don't get from the JSON query is the last one, an input field which is used to fill with a certain amount (Quantity).
What I need to do is: after I fill whatever fields I want, (e.g., the 1st, 4rd and last) I need to cycle through those fields, check which ones are filled and get the value from them.
I can't seem to get the value just from the model, since the model is the same for every field, that's why I'm currently using the 'Enter' button to update the value and send it to an array:
Simple Version:
$scope.arrayQtt = [];
var i = 0;
$scope.setQtt = function(evt){
$scope.arrayQtt[i] = evt.srcElement.value;
i++;
};
It is preferable to check all input fields with a 'Confirmation' button, after all fields are filled, since an user can edit a field the amount of times he wants before clicking the 'Confirmation' button.
Any help, advice or guidance is appreciated.
Thanks in advance!