I have an JSON which is loaded into my Angular2 App.
My JSON is called tempPromotion and i try to get into ['results'] the following way:
tempPromotion['response_payload']['ruleset_list']['results']
in ['results'] are 2 values, ['value_path'] and ['calculation']
my HTML looks like this:
<table class="table table-striped">
<thead>
<tr>
<th>Value Path</th>
<th>Result</th>
<th>TEST</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let result of rule['results']; let x = index">
<td><input type="text" class="form-control" id="valuePath{{x}}" [(ngModel)]="result['value_path']" name="valuePath{{x}}"></td>
<td><input type="text" class="form-control" id="discount{{x}}" [(ngModel)]="result['calculation']" name="discount{{x}}"></td>
<td>{{x}} {{result['calculation']}}</td>
</tr>
</tbody>
</table>
to understand why i use rule, this is alreay inside an other *ngfor <div class="card" *ngFor="let rule of tempPromotion['response_payload']['ruleset_list']; let i = index">
My output looks like this
channel 1 | #Value * 0.8 | 0 #Value * 0.9
channel 1 | #Value * 0.8 | 1 #Value * 0.8
My [(ngModel)] shows the wrong value, while my Two-way-binding {{result['calculation']}} shows the right value.
Why is this happening and what is the solution for this Problem?
I got it to work.
My Problem was that i had the same id / name for my inputs.
change id="valuePath{{x}}" to id="valuePath{{i}}{{x}}" fixxed it.
Related
I have an array of objects with nested arrays as shown below. How can I print the nested array values in a table using ngFor.
The array looks as follows:
I am using a table to print this values so I can export the table to Excel sheet.
The table looks as follows:
<table class="table table-bordered">
<thead class="thead-dark">
<tr>
<th>Hours</th>
<th>Dates</th>
<th>Project Codes</th>
</tr>
</thead>
<tbody class="tbody" *ngFor="let value of array; let i = index">
<tr *ngFor="let item of array[i].item; let dateValue of array[i].datesArray; let h of array[i].hours">
<td>{{h}}</td>
<td>{{dateValue}}</td>
<td>{{value.projectCodeInput}}</td>
</tr>
</tbody>
</table>
I am using multiple arrays on single tag in ngFor like this:
{*ngFor="let item of array[i].item; let dateValue of array[i].datesArray; let h of array[i].hours"}
I know this is wrong way, but somehow the hours prints in the output in both places overriding the dateValue in second column.
Is there a way to print the values from hours, dateValue array in the same element(TABLE)?
Instead of having multiple inputs to the *ngFor directive, you could move the let i=index to the inner loop and use it to get the values.
I assume all the sub-arrays will always be of equal length i.e. hours, datesArray and item array will always be of equal length.
If you wish to span the projectCodeInput property across multiple rows since it'll be the same for each element of the parent array, you could do so using [attr.rowspan] property and first local variable of the *ngFor directive. The check is to make sure the span element is rendered only once for the loop.
<table class="table table-bordered">
<thead class="thead-dark">
<tr>
<th>Hours</th>
<th>Dates</th>
<th>Project Codes</th>
</tr>
</thead>
<tbody class="tbody" *ngFor="let element of arr">
<tr *ngFor="let item of element.item; let i=index; let f=first">
<td>{{element.hours[i]}}</td>
<td>{{element.datesArray[i]}}</td>
<td *ngIf="f" [attr.rowspan]="element.item.length">{{element.projectCodeInput}}</td>
</tr>
</tbody>
</table>
Working example: Stackblitz
You could use the index of the inner loop and get the values with this index z:
<table class="table table-bordered">
<thead class="thead-dark">
<tr>
<th>Hours</th>
<th>Dates</th>
<th>Project Codes</th>
</tr>
</thead>
<tbody class="tbody" *ngFor="let value of array; let i = index">
<tr *ngFor="let item of array[i].item; let z = index">
<td>{{array[i].hours[z]}}</td>
<td>{{array[i].datesArray[z]}}</td>
<td>{{value.projectCodeInput}}</td>
</tr>
</tbody>
</table>
I've used [row] attribute but still not working and when the data reflects on UI I want it in descending order. Can anyone please let me know how it is done without adding sorting Icon?
More
{{col.header}}
{{rowData[col.field]}}
</tr>
</ng-template>-->
<ng-template pTemplate="body" let-rowData let-columns="columns">
<tr [pSelectableRow]="rowData">
<td style="width:300px">{{rowData.atomName}} </td>
<td style="width:300px" (click)="show(rowData.message,op2.show($event))" pTooltip="View" tooltipPosition="top" tooltipStyleClass="custom-tooltip">
{{rowData.processName}}<!--</td>-->
<!--<td style="width:20px">-->
</td>
<td style="width:20px">
<!--{{rowData.executionTime}}-->
{{rowData.executionTime | date :'MM/dd/yyyy' }} ({{rowData.executionTime | date :'h:mm:ss a' }})
</td>
</tr>
</ng-template>
</p-table>
</p-panel>
</div>
It looks more like Angular Js than Angular 8 but if referring to Angular 8 -
Only possible solution to this is sort in the TS file using Array Sort (refer link - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort). and then display only 5 top results using *ngFor and index inside *ngFor.
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.
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">
I create a html table with angular js. But getting problem to make its order reverse.
<tr ng-repeat="(key, val) in qr_score_list ">
<td>{{key}}</td>
<td>{{val}}</td>
</tr>
But don't know how to set its order reverse w.r.t. keys.
The condition is i cant change array sturcture.
Here is my object -:
$scope.qr_score_list = {'6':99,'5.5':98,'5':93,'4.5':80,'4':56,'3.5':38,'3':15,'2.5':7,'2':2,'1.5':1,'1':1,};
The main problem is Javascript doesn't support object keys ordering,
You can try something like this:
<tr ng-repeat="key in Object.keys(qr_score_list).reverse() ">
<td>{{key}}</td>
<td>{{qr_score_list[key]}}</td>
</tr>
have you tried ?
<tr ng-repeat="(key, val) in qr_score_list | orderBy:'$index':true">
<td>{{key}}</td>
<td>{{val}}</td>
</tr>
this also may work :
<tr ng-repeat="(key, val) in qr_score_list | orderBy:'-$index':true">
<td>{{key}}</td>
<td>{{val}}</td>
</tr>