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

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?

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

How to dynamically add HTML element/content - Angular

What would be the best way to dynamically add an HTML element, such as another column onto a basic HTML table?
I want to have a button below the table, and if the user were to click the button, the event would add the same amount of rows already in the table and add another column. I would want to support about 5 extra columns being added to the table.
Here's my HTML table as of right now:
<table>
<thead>
<tr>
<th id="row-tag"></th>
<th id="option-column">Option 1</th>
</tr>
</thead>
<tbody>
<tr>
<td id="row-tag">P</td>
<td id="option-column">{{ p }}</td>
</tr>
<tr id="row-tag">
<td>
<app-a-p (saveButtonClick)="toggleAP($event)"
[modModalValues]="modModalValues">
</app-a-p>
</td>
<td id="option-column">
<div class="input-group input-group-sm">
$<input
*ngIf="toggleAP==true"
type="text"
name="aP"
size="10"
disabled
value=""
/>
<input
*ngIf="toggleAP==false"
type="text"
name="aP"
size="10"
[ngModel]="con.pA"
(ngModelChange)="con.pA = $event" appFormatP
(blur)="checkAP($event.target.value);
inputTracker.addModifiedValue('Option 1', $event.target.value)"
/>
</div>
</td>
</tr>
<tr>
<td id="row-tag">L</td>
<td id="option-column">${{l}}</td>
</tr>
<tr>
<td id="row-tag">R</td>
<td id="option-column">${{r}}</td>
</tr>
</tbody>
</table>
I think in Angular, you define table based on your data. for example, you have fields array defining columns, and data array defines the what's actually in the table.
<table >
<thead>
<tr>
<th *ngFor='let key of this.fields'>{{key}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor='let row of this.data ' >
<td scope="row" *ngFor='let key of this.fields'> {{row[key]}} </td>
</tr>
</tbody>
</table>
when you need a new column, just push a new field into fields. like
fields.push('newcolumn');
when you need a new row, just do:
data.push({col1: '', col2:'', newcolumn: ''});
Look into the insertRow() and insertCell() functions in JavaScript. This alongside an onClick function that you write will let you edit the table.
A good way of generating a table on UI when using angular would be to use 2D-array (row*column) use can have a button using which you can dynamically add values to this array and have another row/column to the table.

Filling all input fields

There is a markup:
<div class="scroll">
<table class="table table-striped">
<thead>
<tr>
<th>Image</th>
<th>Name</th>
<th>Author</th>
<th>Year</th>
<th>ISBN</th>
<th>Price</th>
<th>Count</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let book of bookService.bookList">
<td><img src="../../{{book.ImagePath}}" width="100" height="150"></td>
<td>{{book.Name}}</td>
<td>{{book.Author}}</td>
<td>{{book.Year}}</td>
<td>{{book.ISBN}}</td>
<td>{{book.Price}}</td>
<td>{{book.Count}}</td>
<td>
<input type="text" name="Count" [(ngModel)]="Count">
<button class="btn btn-block btn-outline-success" (click)="onAdd(book, Count)"><i class="fa fa-plus"></i></button>
</td>
</tr>
</tbody>
The last column looks like this:
The problem is the following: when filling one TextBox, all the TextBoxes in the column are filled.
How can I solve this problem? Tried to give unique names to text fields and to thrust this cell in form, but all the same did not work.
You need to give unique name to the input field using angular template
<input [name]="'count' + i" >
Where i is the index from the *ngFor
But I think the major issue you have is that you need to bind book.Count instead of just Count
In latter case you'll have one variable called Count and you bind the same variable to all of the input fields. You need to attach the variable to the book itself so it is unique.
All your inputs have the same [(ngModel)]="Count" and the same name so if you update one, all of them will be updated
You can fix that if you have an array of count instead. So it will be something like
<tr *ngFor="let book of bookService.bookList; let i = index">
...
<input type="text" [name]="'count' + i" [(ngModel)]="count[i]">
People are giving you the HTML way, I'm giving you the Angular way : trackBy functions.
*ngFor="let book of bookService.bookList; trackBy: book.Name"
This one should work but I've never tested it.
The one should work in any case :
*ngFor="let book of bookService.bookList; trackBy: customTB"
customTB(item, index) {
return `${index}-${item.Name}`;
}
You can't use the same name for your inputs.
To fix this, you can add an id populate by the index of the loop *ngFor
Try this :
<tr *ngFor="let book of bookService.bookList; let i = index">
<input type="text" name="Count_${i}" [(ngModel)]="count">

Switching columns and rows with ng-repeat

I am trying to make a series of rows based off of an array of objects. i am trying to produce a series of columns displaying each property of the objects (each has the same properties), with rows showing the property values.
I am currently using the following code.
<div ng-controller="HomepageController" >
<!-- form holding the name -->
<form td-ui-grid-row ng-controller="HomepageController"
ng-submit="vm.addData()" class="form-inline party-form" ng-repeat="dataEntry in vm.dataList">
<div td-ui-grid-col="3xs" ng-repeat="dataContent in dataEntry">
dataContent:{{dataContent}}
</div>
</form>
</div>
vm.data is the following series of data: [{"name":"davis","phone":"11111111111"},{"name":"graeham","phone":"222222222222"},{"name":"eric","phone":"33333333333"}]
and i want to produce the table of vales to look like:
davis graeham eric
11111111111 222222222222 33333333333
however, I am getting the inverse:
davis 11111111111
graeham 222222222222
eric 33333333333
I simplified the code so that it is easier to look and work with:
<div ng-controller="HomepageController" >
<!-- form holding the name -->
<form td-ui-grid-row ng-controller="HomepageController" ng-submit="vm.addData()" class="form-inline party-form">
<table>
<tr>
<td ng-repeat="person in vm.dataList">
<input ng-model="vm.newData.name" type="text" class="form-control" placeholder="{{person.name}}" required>
</td>
</tr>
<tr>
<td ng-repeat="person in vm.dataList">
<input ng-model="vm.newData.name" type="text" class="form-control" placeholder="{{person.phone}}" required>
</td>
</tr>
</table>
</form>
</div>
This code is now showing the proper output format, however i need to be able to cycle through any number of object attributes
.directive('tdUiGridRow', function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
element.addClass('td-row');
if (attrs.tdUiGridRow) {
element.addClass('td-row-type-'+attrs.tdUiGridRow);
}
}
};
})
Please do below. You would create two loops, one for name and one for phone.
<div><span ng-repeat="contact in vm.data">{{contact.name}}</span></div>
<div><span ng-repeat="contact in vm.data">{{contact.phone}}</span></div>
This simply requires looping through the data multiple times, and extracting one property each time.
<table>
<tr>
<td ng-repeat="person in data">{{person.name}}</td>
</tr>
<tr>
<td ng-repeat="person in data">{{person.phone}}</td>
</tr>
</table>
http://plnkr.co/edit/tXmaTmPuwbsN62cQLJuF?p=preview

ASP How to get a value from HTML column

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>