Binding knockout foreach with a table row - html

I have the below table structure
<table style="width: 100%;">
<tr>
<td><b>Fund Value:</b></td>
<td data-bind="text: ItemDetails().FundValue"></td>
<td><b>Fund Code:</b></td>
<td data-bind="text: ItemDetails().FundCode"></td>
<td><b>Fund Desc:</b></td>
<td data-bind="text: ItemDetails().FundDesc"></td>
</tr>
<tr data-bind="foreach: ItemDetails().PriceRebates">
<td><b>Rebate Value:</b></td>
<td data-bind="text: RebateValue"></td>
<td><b>Rebate Code:</b></td>
<td data-bind="text: RebateCode"></td>
<td><b>Rebate Desc:</b></td>
<td data-bind="text: RebateDesc"></td>
</tr>
</table>
It's bound to the knockout viewmodel. The issue I am having is that the tr is bound to the foreach loop and so it is creating multiple td for the ItemDetails().PriceRebates knockout data which I do not want. I want multiple tr to be created for the ItemDetails().PriceRebates data. Can someone please tell me how I can achieve that.
Thanks

You can use foreach without a container element:
<!-- ko foreach: ItemDetails().PriceRebates -->
<tr>
<td><b>Rebate Value:</b></td>
<td data-bind="text: RebateValue"></td>
<td><b>Rebate Code:</b></td>
<td data-bind="text: RebateCode"></td>
<td><b>Rebate Desc:</b></td>
<td data-bind="text: RebateDesc"></td>
</tr>
<!-- /ko -->

Related

Pdf comes blank after a certain page

I am converting my html template to Pdf in Angular. But there is no problem when it is a 7 page pdf. When it's more than 7 pages, the pdf is blank. Page count is output but data is not coming. I couldn't figure out what the problem was, nor am I getting an error. I'm checking my services, my queries are dropping successfully. A front screen opens where I see my html template, and data comes in there. But after a certain page the pdf is blank.`
Thank you, for your help.
I don't get an error either, but strangely 8 pages and then the pdf is blank.
My html template ;
<mat-dialog-content class="print-content" id="print-content">
<div id="print-section">
<table *ngIf="table" class="print-table" id="print-table">
<tr>
<span *ngFor="let row of table;let indexOfCard=index;" >
<span *ngIf="indexOfCard % 2 == 0 && indexOfCard>0"><tr></tr></span>
<td class="print-card">
<table style="border-collapse: separate; border-spacing: 1px 2px;">
<tr rowspan="2" [ngClass]="getHeaderFormat(row.gender,row.departmentID)">
<td colspan="1" > {{row.groupName}} - {{row.shippingCode.toString().padStart(5, "0")}}</td>
<td colspan="6" [ngClass]="getHeaderFormat(row.gender,row.departmentID)"> {{row.staffName}}</td>
</tr>
<tr >
<td colspan="3" [ngClass]="getHeaderFormat(row.gender,row.departmentID)">{{row.departmentName}} {{row.titleName}} {{row.genderName}}</td>
<td colspan="2" [ngClass]="getHeaderFormat(row.gender,row.departmentID)" align="right"> {{row.staffID}}</td>
</tr>
<tr>
<td colspan="2" [ngClass]="getHeaderFormat(row.gender,row.departmentID)">{{row.stationInfo}} {{row.stationName}}</td>
</tr>
<tr>
<td colspan="3">
<table class="report-cell">
<tr *ngFor="let detailList of row.detailList;let indexOfelement=index;">
<ng-container *ngIf="indexOfelement<8 && detailList.quantity>0">
<td [ngClass]="getCellFormat(row.gender,1,row.departmentID)"> {{detailList.generic}}</td>
<td [ngClass]="getCellFormat(row.gender,2,row.departmentID)"> {{detailList.size}}</td>
<td [ngClass]="getCellFormat(row.gender,3,row.departmentID)"> {{detailList.quantity}} Adet</td>
</ng-container>
<span *ngIf="indexOfelement<8 && detailList.quantity<1">
<td [ngClass]="getCellFormat(row.gender,1,row.departmentID)"> </td>
<td [ngClass]="getCellFormat(row.gender,2,row.departmentID)"> </td>
<td [ngClass]="getCellFormat(row.gender,3,row.departmentID)"> </td>
</span>
</tr>
</table>
</td>
<td style="border-left: 1px solid #ddd; padding-left: 10px; vertical-align: top;">
<table class="report-cell">
<ng-container *ngFor="let detailList of row.detailList;let indexOfelement=index;">
<tr *ngIf="indexOfelement>7 && detailList.quantity>0">
<td [ngClass]="getCellFormat(row.gender,1,row.departmentID)"> {{detailList.generic}}</td>
<td [ngClass]="getCellFormat(row.gender,2,row.departmentID)"> {{detailList.size}}</td>
<td [ngClass]="getCellFormat(row.gender,3,row.departmentID)"> {{detailList.quantity}} Adet</td>
</tr>
</ng-container>
</table>
</td>
</tr>
<tr>
<td style="background-color: rgb(252, 252, 252); vertical-align: bottom;"> <img src="./assets/img/thyLogo.jpg" width="50" height="50"/></td>
<td colspan="6">Toplam : {{getTotal(row.detailList)}} Adet</td>
</tr>
</table>
</td>
</span>
</tr>
</table>
---> Html to pdf converter function in Angular
pdfPrint() {
this.exportAsService.save({ type: 'pdf', elementId: 'print-table',options: { jsPDF: {orientation: 'landscape'} }}, this.filename).subscribe(() => {
});
}

Knockout JS inside table collapse two columns depending on visibility

I'm pretty new in Knockout JS binding and I have this table which is supposed to be a row with a single column with the button if the Confirmed text is empty and two separate columns in other way.
Here is what I've tried so far,
<table class="table" id="Mytable" style="table-layout: fixed;">
<tbody data-bind="foreach: info">
<tr>
<td style="vertical-align:middle;">
<button type="button" class="btn2 btn-default" data-bind="click:$root.getClick, trimText:shortName, trimTextLength: 5, css: Confirmed == '' ? colspan='2' : ''">22</button>
</td>
<td style="vertical-align:middle">
<span style="color:green" data-bind="text: Confirmed, visible: Confirmed != ''">10</span>
</td>
</tr>
</tbody>
</table>
but it seems that it doesn't display the info correctly and I don't know what am I doing wrong.
Please be gentle with me, I'm trying to learn from mistakes.
colspan is an attribute, which you set using the attr binding:
data-bind="attr: { 'colspan': Confirmed() ? 1 : 2 }"
In your specific case, I'd use a virtual if binding to switch between the two cases:
<table>
<tbody data-bind="foreach: info">
<tr>
<!-- ko if: Confirmed -->
<td colspan="2">
<button type="button"
data-bind="click:$root.getClick, trimText:shortName, trimTextLength: 5">22</button>
</td>
<!-- /ko -->
<!-- ko ifnot: Confirmed -->
<td></td>
<td>
<span data-bind="text: Confirmed"></span>
</td>
<!-- /ko -->
</tr>
</tbody>
</table>

HTML Table - Nested Table Row using Knockout

I have a JSON object where EntityCode, EntityName, TagName, and TaskName (from TagList) are to be table column headers.
StatusFlagName in TaskRecordList is then to be in a nested row under it's related TaskName. The StatusFlagName values should be directly below the TaskName.
How do I get this working? The StatusFlagName will not display.
var ViewModel = function() {
this.taskRecords = ko.observableArray([
{
EntityCode: "name",
EntityName: "name desc23",
TagName: "L1",
TaskList: [
{
TaskName: "TaskABC",
TaskRecordList: [
{
StatusFlagName: "OK"
},
{
StatusFlagName: "TEST"
}
]
},
{
TaskName: "TaskDEF",
TaskRecordList: [
{
StatusFlagName: "Error"
}
]
}
]
}
]);
};
ko.applyBindings(new ViewModel());
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<table class="table table-bordered">
<tbody data-bind="foreach: taskRecords">
<tr>
<td data-bind="text: EntityCode"></td>
<td data-bind="text: EntityName"></td>
<td data-bind="text: TagName"></td>
<td></td>
<!--ko foreach: TaskList-->
<td data-bind="text: TaskName">
<table>
<tbody>
<!--ko foreach: TaskRecordList-->
<tr>
<td data-bind="text: StatusFlagName"></td>
</tr>
<!--/ko-->
</tbody>
</table>
</td>
<!--/ko-->
</tr>
</tbody>
</table>
When you use <td data-bind="text: TaskName"> knockout will replace whatever you have inside this tag with the value of TaskName as a text that's why your last nested table is being replaced with TaskName value.
You can add a div or span for TaskName something like below :
<table class="table table-bordered">
<tbody data-bind="foreach: taskRecords">
<tr>
<td data-bind="text: EntityCode"></td>
<td data-bind="text: EntityName"></td>
<td data-bind="text: TagName"></td>
<td></td>
<!--ko foreach: TaskList-->
<td>
<div data-bind="text: TaskName"></div>
<table>
<tbody>
<!--ko foreach: TaskRecordList-->
<tr>
<td data-bind="text: StatusFlagName"></td>
</tr>
<!--/ko-->
</tbody>
</table>
</td>
<!--/ko-->
</tr>
</tbody>
</table>

How can I render this irregular table with ng-repeat?

Here I have a JSON data as below:
[
{"teacher":"Tom","student":[{"name":"stuA","project":"projectA"},{"name":"stuB","project":"projectB"}]},
{"teacher":"Jerry","student":[{"name":"stuC","project":"projectC"},{"name":"stuD","project":"projectD"},{"name":"stuE","project":"projectE"}]},
{"teacher":"Lee","student":[{"name":"stuF","project":"projectF"}]}
]
And now I want to render it into an irregular table like the picture:
So how can I make it possible by using ng-repeat? It's really a confusing problem.
Here is the html code that makes the table above:
<tr style="height:40px" >
<td rowspan="2" style="text-align:center;background:#FFD4D4;font-weight:bold;">Tom</td>
<td style="text-align:center;font-size:15px;font-weight:bold;">stuA</td>
<td style="text-align:left;padding-left:100px;font-size:15px;font-weight:bold;">projectA</td>
</tr>
<tr style="height:40px;">
<td style="text-align:center;font-size:15px;font-weight:bold;">stuB</td>
<td style="text-align:left;padding-left:100px;font-size:15px;font-weight:bold;">projectB</td>
</tr>
<tr style="height:40px">
<td rowspan="3" style="text-align:center;background:#FFD4D4;font-weight:bold;">Jerry</td>
<td style="text-align:center;font-size:15px;font-weight:bold;">stuC</td>
<td style="text-align:left;padding-left:100px;font-size:15px;font-weight:bold;">projectC</td>
</tr>
<tr style="height:40px;">
<td style="text-align:center;font-size:15px;font-weight:bold;">stuD</td>
<td style="text-align:left;padding-left:100px;font-size:15px;font-weight:bold;">projectD</td>
</tr>
<tr style="height:40px;">
<td style="text-align:center;font-size:15px;font-weight:bold;">stuE</td>
<td style="text-align:left;padding-left:100px;font-size:15px;font-weight:bold;">projectE</td>
</tr>
I'd suggest you to take use of tbody tag so that we need to apply to ng-repeat tag twice, that would do the trick for you.
Makrup
<table class="table table-bordered">
<thead></thead>
<tbody ng-repeat="teacher in teachers">
<tr ng-repeat="student in teacher.student">
<td ng-if="$first" rowspan="{{teacher.student.length}}">{{teacher.teacher}}</td>
<td>{{student.name}}</td>
<td>{{student.project}}</td>
</tr>
</tbody>
<tfoot></tfoot>
</table>
Demo Plunkr
ng-repeat with tables/table rows can be a bit tricky. Tried to get it done, looks a bit ugly but it does the work:
<tr ng-repeat-start="group in data">
<td ng-bind="group.teacher" rowspan="{{group.student.length}}"></td>
<td ng-bind="group.student[0].name"></td>
<td ng-bind="group.student[0].project"></td>
</tr>
<tr ng-repeat="student in group.student | limitTo : group.student.length - 1 : 1">
<td ng-bind="student.name"></td>
<td ng-bind="student.project"></td>
</tr>
<tr ng-repeat-end></tr>
Plunker: http://plnkr.co/edit/yUPEGdofvwMipcX7CpDK?p=preview

header row in knockout

I want to have some HTML like the following:
<table>
<tbody>
<tr data-bind="foreach: foo">
<td>some header</td>
<td data-bind="value: bar"></td>
</tr>
</tbody>
</table>
I want repeated cells generated by a Knockout foreach binding. But how can I do this while having a header cell which I don't want repeated? The desired output, after binding, is something like:
<table>
<tbody>
<tr>
<td>some header</td>
<td>fred</td>
<td>wilma</td>
<td>barney</td>
<td>bam-bam</td>
</tr>
</tbody>
</table>
The same question applies to having a header row. If the foreach binding is on the <tr> element, how do I tell Knockout not to repeat the first row or cell?
You can use the containerless version of the binding ( see in the documentation: Using foreach without a container element section)
<table>
<tbody>
<tr>
<td>some header</td>
<!-- ko foreach: foo -->
<td data-bind="text: bar"></td>
<!-- /ko -->
</tr>
</tbody>
</table>
Demo JSFiddle.
So the same technique can be used if you want to have a fixed header row:
<table>
<tbody>
<tr>
<td>some header</td>
</tr>
<!-- ko foreach: foo -->
<tr>
<td data-bind="text: bar"></td>
</tr>
<!-- /ko -->
</tbody>
</table>
You can use this
<table>
<tbody>
<tr>
<td>Some header</td>
<!-- ko foreach: foo -->
<td data-bind="value: bar"></td>
<!-- /ko -->
</tr>
</tbody>
</table>
To repeat tr you can use same desicion, but it better to use html possibilities
<table>
<thead>
<tr>
<td> Header </td>
</tr>
</thead>
<tbody>
<tr data-bind="foreach: foo">
<td data-bind="text: bar"></td>
</tr>
</tbody>
</table>