Why Knockout ignore HTML Code Binding? - javascript

I`m using KnockoutJS to bind to a table in WINJS App , when I run My App at the first time , it runs well with correct binding .
this is the Row.innetHTML =
<tbody id="repeater" data-bind="foreach: labsTableArrayKo"
<tr class="tr">
<td><span data-bind="text: VlabName"></span></td>
<td><span data-bind="text: VMType"></span></td>
<td>
<div data-bind="if: VMType == 'Virtual Machine'">
<span data-bind="text: vmStatus"></span>
</div>
<div data-bind="if: VMType == 'RemoteApp'">
<span data-bind="text: 'Ready'"></span>
</div>
</td>
</tr>
but when I change Array which use in binding , Some of HTML Code is Deleted ( I dont know How ?! ) .
the Row.InnetHTML is =
<tr class="tr">
<td><span data-bind="text:VlabName"></span></td>
<td><span data-bind="text: VMType"></span></td>
<td>
<div data-bind="if: VMType == 'Virtual Machine'"></div>
<div data-bind="if: VMType == 'RemoteApp'"></div>
</td>
</tr>
here is how I bind To HTML Code by Javascript :
var viewModel = {labsTableArrayKo: labs_Table_Array};
ko.cleanNode(document.getElementById("repeater"));
var q = document.getElementById("repeater").innerHTML;
ko.applyBindings(viewModel, document.getElementById("repeater"));
So what is the problem ??

actually I replaced (If) with (visible) and it works with me , I don't know exactly why but it works .

Related

Hyperlink not working in table row with click event

I have a table with 4 rows that are repeated by a knockout foreach in the <tbody>. The first row is a Basketball Match and the other 3 rows are the Task performers (referee etc) of the match. I have in the match row a hyperlink to a details page of the location of the sportshall in the city were the match will be played.
The problem is that the performer rows can be expanded and collapsed. This all works fine but now the hyperlink is not working anymore because then the knockout click event is fired. When I do a right mouse click on the hyperlink and say "open in new tab" the hyperlink works fine. So the problem is that the row knockout click is overruling the hyperlink.
Of course I can exclude the TD of the hyperlink and add the collapse click event to the other TDs but that is not what I want.
<tbody data-bind="foreach: Matches">
<tr class="hover-row" data-rowtype="Match" data-bind="click: ExpandTaskToggle">
<td><i class="glyphicon" data-bind="css: IconExpanded"></i></td>
<td data-bind="text: Time"></td>
<td class="hidden-lg hidden-md" data-bind="text: Team.ShortName"></td>
<td class="hidden-sm hidden-xs" data-bind="text: Team.Name"></td>
<td data-bind="text: Opponent"></td>
<td class="hidden-xs" data-bind="text: Location.City"></td>
<td><a data-bind="text: Location.SportsHallName, attr: { href: '/SportLocation/Details/' + Location.Id() }"></a></td>
</tr>
<!-- ko if: IsExpanded -->
<tr data-rowtype="Task">
<td class="striped"></td>
<td colspan="2" class="striped">
<strong>Scheidsrechters </strong>
</td>
<td colspan="2" class="striped" data-bind="foreach: Referees">
<span data-bind="text: PerformerFullName, style: { 'background-color': SelectedPerformerBackground }"></span><span data-bind="if: $index() != ($parent.Referees.length - 1)">, </span>
</td>
<td class="hidden-xs striped"></td>
</tr>
<tr data-rowtype="Task">
<td class="striped"></td>
<td class="striped">
<strong>Scorer </strong>
</td>
<td class="striped" data-bind="foreach: Scorers">
<span data-bind="text: PerformerFullName, style: { 'background-color': SelectedPerformerBackground }"></span><span data-bind="if: $index() != ($parent.Scorers.length - 1)">, </span>
</td>
<td class="striped">
<strong>Timer </strong>
</td>
<td class="striped" data-bind="foreach: Timers">
<span data-bind="text: PerformerFullName, style: { 'background-color': SelectedPerformerBackground }"></span><span data-bind="if: $index() != ($parent.Timers.length - 1)">, </span>
</td>
<td class="hidden-xs striped"></td>
</tr>
<tr data-rowtype="Task">
<td class="striped"></td>
<td colspan="2" class="striped">
<strong>Zaalwacht </strong>
</td>
<td colspan="2" class="striped" data-bind="foreach: SportsHallGuards">
<span data-bind="text: PerformerFullName, style: { 'background-color': SelectedPerformerBackground }"></span><span data-bind="if: $index() != ($parent.SportsHallGuards.length - 1)">, </span>
</td>
<td class="hidden-xs striped"></td>
</tr>
<!-- /ko -->
</tbody>
From the documention to knockout:
Note 3: Allowing the default click action By default, Knockout will prevent the click event from taking any default action. This means that if you use the click binding on an a tag (a link), for example, the browser will only call your handler function and will not navigate to the link’s href.
<...> However, if you do want to let the default click action proceed, just return true
from your click handler function.
And:
Note 4: Preventing the event from bubbling <...> If necessary, you can prevent the event from bubbling by including an
additional binding that is named clickBubble and passing false <...>
I think something like this should work:
<a data-bind="text: Location.SportsHallName, attr: { href: '/SportLocation/Details/' + Location.Id() }, click: function() { return true; }, clickBubble: false"></a>

How can I count the foreach loops in the HTML page?

I have this code:
<div class="main">
<form id="uploadFile" data-bind="attachForm: uploadFile">
<div id="queue"></div>
<input id="file_upload" name="file_upload" type="file" multiple = "true">
<input type="hidden" id="SESSION" name="SESSION" data-bind="value: session" />
</form>
<table class="dataTable" name="details">
<thead>
<tr>
<th data-bind="text: MDCode"></th>
<th data-bind="text: TargetAchieved"></th>
<th data-bind="text: Month"></th>
<th data-bind="text: Year"></th>
<th data-bind="text: MDName"></th>
<th data-bind="text: Document"></th>
</tr>
</thead>
<tbody data-bind="foreach: mainData">
<tr>
<td data-bind="text: MDCode"></td>
<td data-bind="text: targetAchieved"></td>
<td data-bind="text: month"></td>
<td data-bind="text: year"></td>
<td data-bind="text: MDName"></td>
<td> Open </td>
</tr>
</tbody>
</table>
</div>
I'm using knockoutjs to bind the values. The problem is that I need to count the foreah loop. The mainData is filled by the upload form(on the top). Every attached file is one row in the table. I can not count the mainData inside of my viewmodel, because when it's called themainData is empty.
I also tried:
rowCount = $('#details tr').length;
console.log(rowCount);
But it always returns 0, because when the viewModel is called there are no rows at all.
Please, help me with this issue. I'm pretty sure that the problem is inside of my logic, or I'm missing something really small, but I'm not able to spot it.
you need to change the selector because details is not the id of the table, but is is the name so you need to use the attribute selector
rowCount = $('table[name="details"] tr').length;
$(document).ready(function() {
rowCount = $('table[name="details"] tr').length;
alert(rowCount);
});

How to bind server generated html data into knockout model attribute?

I want to bind back server generated html into knockout model. Is there any manner to do it?
<table>
<tr data-bind="with: dataList">
<td data-bind="text: Name">
Name
</td>
<td data-bind="text: Text">
Text
</td>
</tr>
<tr data-bind="with: dataList">
<td data-bind="text: Name">
Name2
</td>
<td data-bind="text: Text">
Text2
</td>
</tr>
</table>
Stuff like this...
The dataList property of the object you bound to view will contain all the data you are expecting.
You should use ko.mapping.toJS() to convert an observable view model to a raw view model.

KnockoutJS `with` binding and IE8

For some reason my code is generating the error below in IE8, but not in any of the normal browsers.
SCRIPT5022: Unable to parse bindings.
Message: TypeError: 'logoSrc' is undefined;
Bindings value: 'attr': { 'src': logoSrc }
I confirmed that the logoSrc property is indeed defined, even in IE8, right before binding, but still it fails. And disabling the binding to logoSrc just causes the next binding in line to fail.
The html is below. I know I've used a with binding before, so I'm pretty sure that's not the problem, and the html seems to be properly closed.
<div data-bind="visible: mode() === 'print'" class="container-fluid">
<!-- ko with: printVm -->
<div class="row-fluid">
<div class="span12">
<div class="page-header">
<div class="pull-right" style="width:140px;height:60px;overflow:hidden;">
<img data-bind="'attr': { 'src': logoSrc }" src="" />
</div>
<h2>Invoice Statement - <span data-bind="text: itemZeroClientName"></span></h2>
</div>
<strong>Invoice number:</strong> <span data-bind="text: invoiceId"></span>
<strong>Invoice date:</strong> <span data-bind="text: userInfo().invoiceDateDisplay"></span>
<strong>Client number:</strong> <span data-bind="text: itemZeroClientId">22365</span>
<hr />
</div>
</div>
<div class="row-fluid">
<div class="span6 cr-tablet6 cr-phone6">
<h4>Billed by <span data-bind="text: companyNameDisplay"></span></h4>
<span data-bind="html: companyInfo"></span>
</div>
<div class="span6 cr-tablet6 cr-phone6">
<h4>Billed to</h4>
<span data-bind="html: clientInfoDisplay"></span>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<hr />
<table id="printInvoiceTable" class="table">
<thead>
<tr>
<th class="date">Date</th>
<th class="name">Provider</th>
<th class="code">Proc Code</th>
<th class="location">Location</th>
<th class="time">Hours</th>
<th class="units">Units</th>
<th class="charge">Charges</th>
</tr>
</thead>
<tbody data-bind="foreach: items">
<tr>
<td data-bind="text: dateDisplay"></td>
<td data-bind="text: orgName"></td>
<td data-bind="text: procedureCodeString"></td>
<td data-bind="text: location"></td>
<td class="formatted-number" data-bind="text: timeWorkedHrs"></td>
<td class="formatted-number" data-bind="text: (unitsOfService() || 0).toFixed(2)"></td>
<td class="formatted-currency" data-bind="text: (clientCharges() || 0).toFixed(2)"></td>
</tr>
</tbody>
<tfoot>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td class="formatted-number" data-bind="text: totalWorkedHours"></td>
<td class="formatted-number" data-bind="text: totalUnitsOfService"></td>
<td class="formatted-currency" data-bind="text: totalClientRate"></td>
</tr>
</tfoot>
</table>
</div>
</div>
<!-- /ko -->
</div>
As suggested above, it seems the issue is with IE8 removing comments (and thus virtual bindings in some conditions) and has been reported on the knockout forums
I have had issues using with and jquery file upload in IE8. I also had issues with comments and was able to fix it by escaping the comment condition. the knockout webpage mentions this warning.

Knockout.js -- understanding foreach and with

I've been going through the learn.knockout.js tutorials and been experimenting. Can someone explain why this works [Tutorial: Single page applications, Step 2] (using with: chosenFolderData and foreach: mails):
<!-- Mails grid -->
<table class="mails" data-bind="with: chosenFolderData">
<thead><tr><th>From</th><th>To</th><th>Subject</th><th>Date</th></tr></thead>
<tbody data-bind="foreach: mails">
<tr>
<td data-bind="text: from"></td>
<td data-bind="text: to"></td>
<td data-bind="text: subject"></td>
<td data-bind="text: date"></td>
</tr>
</tbody>
</table>
but not this (using just foreach: chosenFolderData.mails):
<!-- Mails grid -->
<table class="mails">
<thead><tr><th>From</th><th>To</th><th>Subject</th><th>Date</th></tr></thead>
<tbody data-bind="foreach: chosenFolderData.mails">
<tr>
<td data-bind="text: from"></td>
<td data-bind="text: to"></td>
<td data-bind="text: subject"></td>
<td data-bind="text: date"></td>
</tr>
</tbody>
</table>
I suspect it's because while chosenFolderData is observable, chosenFolderData.mails is not. Can anyone tell me for certain?
Many thanks!
-- Ralph
Because you are not actually accessing the property you want with the way it is written. In the model chosenFolderData is an observable and must be called like a method to retrieve the value. To provide the functionality without using with (and I suggest not using with where high performance is necessary because of the overhead)...
<tbody data-bind="foreach: chosenFolderData().mails">

Categories

Resources