我正在尝试获取 timeline component of vis.js与 Knockout.js 一起工作。
时间线有 templates option它允许您为时间线上的每个事件编写自定义 HTML。就我而言,它看起来像这样:
var options = {
... // other options
template: function(item) {
var html = '<b>' + item.subject + '</b>'+
'<p>' + item.owner.username + ' (' + item.format.name + ' for ' + item.channel.name + ')</p>' +
'<p><input type="checkbox"';
if (item.done !== null) {
html += "checked"
};
html += '></p>';
html += '<pre data-bind="text: $root"></pre>'; // http://www.knockmeout.net/2013/06/knockout-debugging-strategies-plugin.html
return html;
}
}
所有数据绑定(bind)都经过测试并且正常,但我想不出一种方法将 knockout 行为附加到 vis.js 时间线库生成的模板。正如您所看到的,即使尝试打印 $root 数据也无济于事。
如何将可观察量附加到此模板?
最佳答案
如果您愿意,时间轴组件选项的模板属性允许您提供 HTML 元素而不是 HTML 字符串。这可能是实现您所追求的目标的一种方法。通过这种方式,您可以创建元素,使用 Knockout 使用提供的项目作为上下文在元素(及其子元素)上应用绑定(bind),并将该元素返回到 vis.js。
执行此操作的示例可以使用类似于以下的代码:
var templateHtml = '<div data-bind="text: content"></div>'
//Set the template to a custom template which lets knokcout bind the items
options.template = function(item){
//Create a div wrapper element to easily create elements from the template HTML
var element = document.createElement('div');
element.innerHTML = templateHtml;
//Let knockout apply bindings on the element with the template, using the item as data context
ko.applyBindings(item, element);
//Return the bound element to vis.js, for adding in the component
return element;
};
在 knockout 世界中,为 vis.js 时间轴组件创建自定义的 bindingHandler 当然会更好。
因此,这里还有一个使用自定义绑定(bind)处理程序进行 knockout 的类似示例(这是一个非常简单的示例绑定(bind)处理程序,并不真正支持数据的可观察选项或可观察数组,但它确实支持项目中的可观察值)。
ko.bindingHandlers.visTimeline = {
init: function(element, valueAccessor){
var unwrappedValue = ko.unwrap(valueAccessor());
var data = ko.unwrap(unwrappedValue.data);
var options = ko.unwrap(unwrappedValue.options);
if (options.templateId){
var templateId = ko.unwrap(options.templateId);
var templateHtml = document.getElementById(templateId).innerHTML;
//Set the template to a custom template which lets knokcout bind the items
options.template = function(item){
//Create a div wrapper element to easily create elements from the template HTML
var element = document.createElement('div');
element.innerHTML = templateHtml;
//Let knockout apply bindings on the element with the template, using the item as data context
ko.applyBindings(item, element);
//Return the bound element to vis.js, for adding in the component
return element;
};
}
//Apply the vis.js timeline component
new vis.Timeline(element, data, options);
//Let knockout know that we want to handle bindings for child items manually
return { controlsDescendantBindings: true };
}
};
var items = [
{ id: 1, content: 'item 1', counter: ko.observable(0), start: '2014-04-20'},
{ id: 2, content: 'item 2', counter: ko.observable(0), start: '2014-04-14'},
{ id: 3, content: 'item 3', counter: ko.observable(0), start: '2014-04-18'},
{ id: 4, content: 'item 4', counter: ko.observable(0), start: '2014-04-16', end: '2014-04-19'}
];
var viewModel = {
items: items
};
//Randomly increment the counters of the items, to see that the data is bound
setInterval(function(){
var randomItem = items[Math.floor(Math.random() * items.length)];
randomItem.counter(randomItem.counter() + 1);
}, 500);
ko.applyBindings(viewModel);
<!-- First, let's include vis.js and knockout -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/vis/3.12.0/vis.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vis/3.12.0/vis.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<!-- This is the template we want to use for our items -->
<script type="text/html" id="myCustomTemplate">
<strong data-bind="text: id"></strong>. <span data-bind="text: content"></span>
<div data-bind="text: counter"></div>
</script>
<!-- And this is where we use our bindingHandler -->
<div data-bind="visTimeline: { data: items, options: { templateId: 'myCustomTemplate' } }"></div>
您还可以在 http://jsbin.com/lecidaxobo/1/edit?html,js,output 处看到此片段
关于javascript - 将 Knockout.js 与自定义模板引擎结合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29607214/