在knockout.js完成渲染所有元素后成功callback

我已经实现了一个淘汰赛foreach绑定,在同一页面的多个模板,其中一个例子在这里给出,我感兴趣的是在找出一个块完成渲染时,我试过afterRenderafterAdd ,但我想它运行为每个元素,而不是整个循环完成后。

 <ul data-bind="foreach: {data: Contacts, afterAdd: myPostProcessingLogic}"> <li> <div class="list_container gray_bg mrgT3px"> <div class="list_contact_icon"></div> <div class="contact_name"><span data-bind="text: first_name"></span> <span data-bind="text: last_name"></span></div> <div class="contact_number"><span data-bind="text: value"></span></div> <div class="callsms_container"> <a href="#notification-box" class="notifcation-window"> <div class="hover_btn tooltip_call"> <div class="hover_call_icon"></div> <span>Call</span></div> </a> <a class="sendsms" href="#sendsms" rel="#sendsms"> <div class="hover_btn tooltip_sms"> <div class="hover_sms_icon"></div> <span>SMS</span></div> </a> <a href="#"> <div class="hover_more_btn"></div> </a> </div> <!-- close callsms container --> <div id="notification-box" class="notification-popup"> <a href="#" class="close"><img class="btn_close" src="images/box_cross.png" /></a> <img class="centeralign" src="images/notification_call.png" /> <span>Calling... +44 7401 287366</span> </div> <!-- close notification box --> <!-- close list gray bg --> <div class="tooltip_description" style="display:none" id="disp"> asdsadaasdsad </div> </div> </li> </ul> 

我感兴趣的是找出成功的callback,当一个循环完成渲染。

这里是我的afterAdd函数,它基本上附加了一些jQuery事件,没什么。

 myPostProcessingLogic = function(elements) { $(function(){ $(".list_container_callog").hover(function(){ $(".callsms_container", this).stop().animate({left:"0px"},{queue:false,duration:800}); }, function() { $(".callsms_container", this).stop().animate({left:"-98%"},{queue:false,duration:800}); }); }); } 

在此先感谢,并告诉我有一个成功的callback:)

你有knockout.jsafterRendercallback:

 foreach: { data: myItems, afterRender: renderedHandler } 

这里是文档。

处理程序内部检查渲染集合的长度是否等于items集合的长度。 如果不是,则不要执行您打算使用的完整呈现逻辑。

 renderedHandler: function (elements, data) { if ($('#containerId').children().length === this.myItems().length) { // Only now execute handler } } 

尝试包装ul

 <div data-bind='template: {afterRender: myPostProcessingLogic }'> 

它只会在模板中的所有内容第一次被渲染的时候运行。 但是你只能得到myPostProcessingLogic的一个调用。 这是一个小提琴

 <div data-bind='template: {afterRender: myPostProcessingLogic }'> <ul data-bind="foreach: Contacts"> <li> <div class="list_container gray_bg mrgT3px"> <div class="list_contact_icon"></div> <div class="contact_name"><span data-bind="text: first_name"></span> <span data-bind="text: last_name"></span></div> <div class="contact_number"><span data-bind="text: value"></span></div> <div class="callsms_container"> <a href="#notification-box" class="notifcation-window"> <div class="hover_btn tooltip_call"> <div class="hover_call_icon"></div> <span>Call</span></div> </a> <a class="sendsms" href="#sendsms" rel="#sendsms"> <div class="hover_btn tooltip_sms"> <div class="hover_sms_icon"></div> <span>SMS</span></div> </a> <a href="#"> <div class="hover_more_btn"></div> </a> </div> <!-- close callsms container --> <div id="notification-box" class="notification-popup"> <a href="#" class="close"><img class="btn_close" src="images/box_cross.png" /></a> <img class="centeralign" src="images/notification_call.png" /> <span>Calling... +44 7401 287366</span> </div> <!-- close notification box --> <!-- close list gray bg --> <div class="tooltip_description" style="display:none" id="disp"> asdsadaasdsad </div> </div> </li> </ul> </div> 

只需要使用Knockout的容器less方法将foreach包装到另一个foreach循环中,如下所示:

 <!-- ko foreach:{data: Contacts, afterRender: myPostProcessingLogic }--> <ul data-bind="foreach: $data}"> <li> <div class="list_container gray_bg mrgT3px"> <div class="list_contact_icon"></div> <div class="contact_name"><span data-bind="text: first_name"></span> <span data-bind="text: last_name"></span></div> <div class="contact_number"><span data-bind="text: value"></span></div> <div class="callsms_container"> <a href="#notification-box" class="notifcation-window"> <div class="hover_btn tooltip_call"> <div class="hover_call_icon"></div> <span>Call</span></div> </a> <a class="sendsms" href="#sendsms" rel="#sendsms"> <div class="hover_btn tooltip_sms"> <div class="hover_sms_icon"></div> <span>SMS</span></div> </a> <a href="#"> <div class="hover_more_btn"></div> </a> </div> <!-- close callsms container --> <div id="notification-box" class="notification-popup"> <a href="#" class="close"><img class="btn_close" src="images/box_cross.png" /></a> <img class="centeralign" src="images/notification_call.png" /> <span>Calling... +44 7401 287366</span> </div> <!-- close notification box --> <!-- close list gray bg --> <div class="tooltip_description" style="display:none" id="disp"> asdsadaasdsad </div> </div> </li> </ul> <!-- /ko --> 

上面的解决scheme很好。 此外,如果您需要使用foreach“as”选项,则可以这样做:

 data-bind="foreach: { data: myItems, afterRender: renderedHandlet, as: 'myItem'}"> 

Chuck Schneider上面的答案是最好的。 我不得不使用无容器控制,因为foreach是一个tbody元素:

 <!-- ko template: {afterRender: SetupCheckboxes } --> <tbody data-bind="foreach: selectedItems" id="gridBody"> <tr> <td> <input type="checkbox" /> </td> </tr> </tbody> <!-- /ko --> 

我刚刚做了一个敲击请求,为他们添加两个事件来定义绑定,解包,然后在渲染项目之前和所有项目已渲染之前调用正确的点。 我没有听到任何回复,但是这正是你想要做的,但是你不必写hacky的代码来让它工作。 我很惊讶没有人提出这个要求。 我使用这些callback,我添加到源来销毁和重新初始化敲除绑定jQuery数据表。 这是最简单的解决scheme。 我在网上看到很多尝试,尝试做不同,但这是最简单的解决scheme。

拉请求: – > pr 1856

 ko.bindingHandlers.DataTablesForEach = { init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { var nodes = Array.prototype.slice.call(element.childNodes, 0); ko.utils.arrayForEach(nodes, function(node) { if (node && node.nodeType !== 1) { node.parentNode.removeChild(node); } }); return ko.bindingHandlers.foreach.init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext); }, update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { var value = ko.unwrap(valueAccessor()), key = "DataTablesForEach_Initialized"; var newValue = function() { return { data: value.data || value, beforeRenderAll: function(el, index, data) { if (ko.utils.domData.get(element, key)) { $(element).closest('table').DataTable().destroy(); } }, afterRenderAll: function(el, index, data) { $(element).closest('table').DataTable(value.options); } }; }; ko.bindingHandlers.foreach.update(element, newValue, allBindingsAccessor, viewModel, bindingContext); //if we have not previously marked this as initialized and there is currently items in the array, then cache on the element that it has been initialized if (!ko.utils.domData.get(element, key) && (value.data || value.length)) { ko.utils.domData.set(element, key, true); } return { controlsDescendantBindings: true }; } }; 

Knockout Datatables JSFiddle