Reputation: 1218
This jquery mobile table is being rendered with knockout.
<table data-role="table" id="report-table" class="ui-body-a ui-shadow ui-responsive table-stripe"
data-column-btn-theme="a" data-column-btn-text="Spalten..." data-column-popup-theme="a" data-mode="columntoggle"">
<thead>
<tr data-bind="foreach: columns">
<th data-bind="text: $data.Caption, attr: { 'data-priority': 1 + Math.floor($index() / 4) }"></th>
</tr>
</thead>
<tbody data-bind="foreach: { data: rows, afterRender: tableRowAfterRender }">
<tr data-bind="foreach: $parent.columns">
<!-- ko template: { name: $data.template } -->
<!-- /ko -->
</tr>
</tbody>
</table>
To get the "columntoggle" to actually work, I currently use the "aferRender" event:
self.tableRowAfterRender = function (element, data) {
// Skip unless data.Items()[i] is not the last element in the rows collections
for (var i = 0; i < data.Items().length - 1; i++) {
if (data.Items()[i] !== self.rows()[self.rows().length - 1].Items()[i])
return;
}
// refresh table after 100ms delay
setTimeout(function () { $("#report-table").table("refresh"); }, 100);
}
This is shaky, I hate the setTimeout() way of doing things, and this situation became quiet common for me with jquery mobile and knockout. I need a robust way to raise an event once all the knockout rendering or ideally once all the rendering concerned with elements inside the table-element is done. I was able to use custom bindings in some such situations, but I would not know how to do this here.
Upvotes: 7
Views: 7430
Reputation: 890
You can try to use binding init
ko.bindingHandlers.init = {
init: function(element, valueAccessor, allBindings, viewModel) {
var action = valueAccessor();
if (typeof action === 'function') {
setTimeout(action.bind(viewModel, element), 0);
}
}
};
Like this:
ko.components.register('simple-component', {
viewModel: function(params) {
this.title = params.title;
this.initHandler = function() {
console.log('DOM of component has been built.');
};
},
template:
'<div data-bind="init: initHandler">\
Title is: <span data-bind="text: title"></span>\
</div>'
});
Information for more complex cases is here - http://blog.atott.ru/2015/08/dom-built-event-for-knockout-components.html
Upvotes: 2
Reputation: 19882
There is a simple way of doing it. Here is the process
Assign a class to your row
<tr class="row" data-bind="foreach: $parent.columns">
Check in your function with if condition
if(data.Items().length == $('row').length){
$("#report-table").table("refresh")
}
Or call any event manually
$('#report-table').trigger('click')
Hope that's helpful to you.
EDITS:
Create a new observable and set it to false.
self.EnableTimeOut = ko.observable(false)
Now set it true according to your requirement. This is only example
if(data.Items().length == $('row').length && data.Items().length > 0){
self.EnableTimeOut(true)
$("#report-table").table("refresh")
}
And finally
Wrap it in condition
setTimeout(function () {
if(self.EnableTimeOut()){
$("#report-table").table("refresh");
}
}, 100);
Upvotes: 0
Reputation: 344
Try this. Wrap the table with: <div data-bind='template: { afterRender: myPostProcessingLogic }'>.
Then do whatever you need to do in myPostProsssingLogic. This will only be called when the table is first rendered however. Here's a fiddle:
<div data-bind='template: { afterRender: myPostProcessingLogic }'>
<table data-role="table" id="report-table" class="ui-body-a ui-shadow ui-responsive table-stripe"
data-column-btn-theme="a" data-column-btn-text="Spalten..." data-column-popup-theme="a" data-mode="columntoggle"">
<thead>
<tr data-bind="foreach: columns">
<th data-bind="text: $data.Caption, attr: { 'data-priority': 1 + Math.floor($index() / 4) }"></th>
</tr>
</thead>
<tbody data-bind="foreach: { data: rows, afterRender: tableRowAfterRender }">
<tr data-bind="foreach: $parent.columns">
<!-- ko template: { name: $data.template } -->
<!-- /ko -->
</tr>
</tbody>
</table>
Upvotes: 3