我看过this question和this other一个关于这个主题的内容,但似乎没有一个能解决我的问题。
我正在尝试为表格的每一行中的元素初始化javascript插件(BootStrap javascript工具提示)。
要做到这一点,必须在DOM中呈现表。这就是问题所在。
据我所知,knockout.js没有提供一个正确的方法来知道foreach
何时呈现整个表格。
我试图通过应用我发布的第一个链接中提供的解决方案来解决它,这是通过创建自定义绑定,但这在我的情况下不起作用。 我猜是因为通过从AJAX调用中调用API来显示数据。
ko.bindingHandlers.doSomething = {
update: function (element) {
console.log("table loaded???");
//applying the tooltip
$('.actions').tooltip({
title: 'Actions'
});
}
};
function ViewModel(){
var self = this;
self.myItems= ko.observableArray(['A', 'B', 'C']);
//emulating the delay of calling an external API
self.getdata = function(){
setTimeout(function(){
self.myItems.push('D');
self.myItems.push('E');
self.myItems.push('F');
}, 200);
};
self.addItem = function () {
this.myItems.push('New item');
};
//getting the data on loading
self.getdata();
}
ko.applyBindings(new ViewModel());
我宁愿不使用Knockout.js为afterRender
个案提供的foreach
回调,因为这样插件必须在每次迭代时初始化,而不是在最后一次。< / p>
我找到的唯一解决方案是在应用工具提示插件之前应用setTimeout
,但这远非理想:
ko.bindingHandlers.doSomething = {
update: function (element) {
console.log("table loaded???");
setTimeout(function(){
//applying the tooltip
$('.actions').tooltip({
title: 'Actions'
});
}, 2000);
}
};
另一个解决方案是从API获取数据后调用tooltip
插件:
//emulating the delay of calling an external API
self.getdata = function(){
setTimeout(function(){
//simulating
$.get(url, function(data){
self.orders(data);
self.loading(false);
$('.actions').tooltip({
title: 'Actions'
});
});
}, 200);
};
有没有更好的方法呢?
答案 0 :(得分:1)
这是一个选项,以一种可能更适合的不同方式混合您已经知道的一些内容。
http://jsfiddle.net/xveEP/260/
我首先在viewmodel中添加了一个名为tooltipHandle
的变量。此变量将是用于应用工具提示的任何setTimeout
调用的引用(或指针)。
我为<li>
元素而不是父<ul>
元素创建了自定义绑定。此自定义绑定首先清除任何现有setTimeout
实例以添加工具提示。然后它创建一个将在5ms内运行的新setTimeout
实例。此setTimeout
中的函数会将工具提示应用于.actions
类的所有尚未应用工具提示的元素。
在您的示例中,总共添加了6个元素:3个立即,3个200毫秒。我的绑定将执行6次,但是,它只会应用两次工具提示:一次用于前三次,一次用于第二次3.因为我在清除tooltipHandle
之前才能执行setTimeout
函数,它仅在2组中的每一组完成绑定的第3项之后运行。我在console.log
函数中添加了setTimeout
调用,以便您在上一个示例中看到它只被调用了2次。
此外,当您单击“添加”按钮时,将执行绑定,并且仅将工具提示应用于新添加的元素。
<ul data-bind="foreach: myItems">
<li data-bind="text: $data, doSomething2: true" class="actions"></li>
</ul>
ko.bindingHandlers.doSomething2 = {
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
clearTimeout(bindingContext.$parent.tooltipHandle);
bindingContext.$parent.tooltipHandle = setTimeout(function() {
$('.actions:not([data-original-title])').tooltip({
title: 'Actions'
});
window.console.log('tooltip applied');
}, 5);
}
};
function ViewModel(){
var self = this;
self.tooltipHandle = undefined;
self.myItems= ko.observableArray(['A', 'B', 'C']);
//emulating the delay of calling an external API
self.getdata = function(){
setTimeout(function(){
self.myItems.push('D');
self.myItems.push('E');
self.myItems.push('F');
}, 200);
};
self.addItem = function () {
this.myItems.push('New item');
};
//getting the data on loading
self.getdata();
}
ko.applyBindings(new ViewModel());