Knockout.js -- understanding foreach and with - javascript

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">

Related

Why Knockout ignore HTML Code Binding?

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 .

knockout.js error when binding doesn't exist in foreach [duplicate]

How do I bind a text when it is undefined? For example name is not available:
<table id="recordTbl" data-bind="visible: records().length > 0" class="table">
<thead>
<tr>
<th class="col-md-4">ID</th>
<th class="col-md-4">Name</th>
</tr>
</thead>
<tbody data-bind="foreach: records">
<tr>
<td data-bind="text: id"></td>
<td data-bind="text: name"></td>
</tr>
</tbody>
</table>
I get this error:
Uncaught ReferenceError: Unable to process binding "text: function (){return name }"
Message: name is not defined
You can you the $data binding context property which always represents the current view model to access the name through it:
<tbody data-bind="foreach: records">
<tr>
<td data-bind="text: id"></td>
<td data-bind="text: $data.name"></td>
</tr>
</tbody>
With this approach KO won't throw an exception if one of the items in the records does not have a name property.
Without the $data the identifier named name is undefined. However $data.name is always a valid expression it just returns undefined if the current view model does not have a property named name.

Why the pagination of footable is not working?

I'm trying to implement FooTable-2 in my project, but for some reason I can't get the pagination working.
I'm following THIS tutorial and here is what I have so far as a table code:
<div id="mainContent">
<div id="allTrackersDiv" style="display: none;">
<label><b>Active Trackers</b></label>
<table class="activeTrackersTable" id="allTrackersTable"
data-page-navigation=".pagination">
<thead>
<tr>
<th> ID </th>
<th> col 1 </th>
<th> col 2 </th>
<th> col 3 </th>
</tr>
</thead>
<tbody data-bind="foreach: trackersObjArray">
<tr data-bind="click: test">
<td><span data-bind="text: tId"></span></td>
<td><span data-bind="text: tname"></span></td>
<td><span data-bind="text: pname"></span></td>
<td><span data-bind="text: tcreate"></span></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="4">
<div class="pagination"></div>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
The problem is that the paging is not working. I have 22 records in my table and it is supposed to start paging after the 10th record
Here is how it looks:
What am I missing here? At my point of view everything looks pretty fine. What am I missing, I really can't understand my mistake.
You can try mentioning
data-page-size="10"
explicitly.
And if that doesn't work, may be issue is due to dynamic data being added to footable.
Use
$('#myTable').append(html).trigger('footable_redraw');
So that footable will be redrawed and size limit will be applied.
Reference links: Footable data page size not respected and
Other issues due to dynamic data in footable

How to load list.js dynamically through ajax and for sort to continue working

I have a static HTML page which loads dynamic tables using Ajax. The tables I want to load are sortable tables built using list.js and jQuery. When the tables are coded in line they load and are sortable without issue. As soon as I introduce Ajax, the data appears but sorting no longer works.
I am aware of binding and .on() but I am not sure how to get it working with list.js
Example Code:
<html>
<head>
<script
src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"
src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"
src="//listjs.com/js/list.js"
$(document).ready(function(){
// Define value names
var overview_options = { valueNames: [ 'name', 'term', 'module', 'activity' ] };
// Init list
var overviewList = new List('list_overview', overview_options);
});
function loadTable() {
getTable=new XMLHttpRequest();
getTable.onreadystatechange=function()
{
if (getTable.readyState==4 && getTable.status==200)
{
document.getElementById("tableArea").innerHTML=getTable.responseText;
}
}
getTable.open("GET","tableDate.html",true);
getTable.send();
}
</script>
</head>
<body>
<div onClick="loadTable();">Load Table</div>
<div id="tableArea"></div>
</body>
</html>
And the file Ajax is pulling in:
<div class="list_holder">
<table id="list_overview" cellpadding="10" >
<thead>
<tr>
<th><span class="sort" data-sort="name">Name</span></th>
<th><span class="sort" data-sort="term">Term</span></th>
<th><span class="sort" data-sort="module">Module</span></th>
<th><span class="sort" data-sort="activity">Activity</span></th>
</tr>
</thead>
<tbody class="list">
<tr>
<td class="name">Zack Walker</td>
<td class="term">3</td>
<td class="module">Body Language</td>
<td class="activity">None</td>
</tr>
<tr>
<td class="name">Peter Jones</td>
<td class="term">1</td>
<td class="module">Body Language</td>
<td class="activity">All</td>
</tr>
<tr>
<td class="name">Zack Walker</td>
<td class="term">3</td>
<td class="module">Helping</td>
<td class="activity">All</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
Many thanks!
Just guessing here, shouldn't you be initializing the list after you populate the data in your ajax response?

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.

Categories

Resources