自定义KnockoutJS bindingHandler,用于动态Bootstrap工具提示

时间:2013-12-13 14:45:34

标签: javascript jquery twitter-bootstrap knockout.js

我在这里找到了一些关于使用Bootstrap工具提示和自定义挖空绑定处理程序的其他问题和资源。但是,我还没有找到一个有凝聚力的解决方案,1)涉及使用动态淘汰模板2)工具提示可以在数据绑定变化时发生变化。

我在GitHub上也不在knockout-bootstrap,但其中的工具提示标题只呈现一次,

我创建了一个新的JSFiddle,其新的dynamicTooltip基于之前的JSFiddle

新的DynamicTooltip数据绑定器如下所示:

ko.renderTemplateHtml = function (templateId, data) {
    var node = $("<div />")[0];
    ko.renderTemplate(templateId, data, {}, node);
    return $(node).html();
};

ko.bindingHandlers.tooltip = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
    var local = ko.utils.unwrapObservable(valueAccessor()),
        options = {};

    ko.utils.extend(options, ko.bindingHandlers.tooltip.options);
    ko.utils.extend(options, local);

    var tmplId = options.kotemplate;

    ko.utils.extend(options, {
        title: ko.renderTemplateHtml(tmplId, viewModel)
    });

    $(element).tooltip(options);

    ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
        $(element).tooltip("destroy");
    });
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
    var local = ko.utils.unwrapObservable(valueAccessor()),
        options = {};

    ko.utils.extend(options, ko.bindingHandlers.tooltip.options);
    ko.utils.extend(options, local);

    var tmplId = options.kotemplate;
    var forceRefresh = options.forceRefresh;
    var newdata =  ko.renderTemplateHtml(tmplId, viewModel); 
    $(element).data('bs.tooltip').options.title = newdata

},
options: {
    placement: "top",
    trigger: "hover",
    html: true
}};

它不完整,因为我通过在视图模型上传入一个虚拟数据绑定属性手动触发更新调用,在这种情况下,它被称为renderTooltip():

<a data-bind="tooltip: { title: firstName, placement: 'bottom', kotemplate: 'tile-tooltip-template', forceRefresh: renderTooltip() }">Hover on me</a>

我希望能够在数据发生变化时触发工具提示自我刷新。

我想我应该使用createChildContext(),也许还有controlsDescendantBindings,但我不太确定。

有什么想法?我将继续更新它,因为看起来动态引导工具提示是一个常见的想法。

1 个答案:

答案 0 :(得分:1)

问题的根源是更新绑定未触发,因为它不依赖于您尝试更新的属性(即firstName和address);

通常,您可以将这些属性委托给新绑定,并让knockout自动处理依赖关系跟踪。但是,在这种情况下,您实际上是返回一个字符串,因此无法使用该元素的自动绑定。字符串是必需的,因为这是工具提示的工作方式。如果它可以从DOM元素动态读取,那么自动绑定将起作用,但由于它需要HTML字符串,因此绑定无法影响它。

我看到的几个选项:

<强> 1。自动创建对模板使用的属性的依赖。这可以通过隔离模板视图模型(数据)来完成,如此小提琴中所示:http://jsfiddle.net/tMbs5/13/

//create a dependency for each observable property in the data object
for(var prop in templateData)
    if( templateData.hasOwnProperty(prop) && ko.isObservable(templateData[prop]))
        templateData[prop]();

<强> 2。不使用基于DOM的模板,而是使用ko.computed在视图模型中生成模板。这将根据需要自动创建依赖项。 请参阅此小提琴,获取示例:http://jsfiddle.net/tMbs5/12/

var vm = {
    firstName: ko.observable('Initial Name'),
    address: ko.observable('55 Walnut Street, #3'),
    changeTooltip: function () {
        this.firstName('New Name');
    }
};

vm.tooltipHtml = ko.computed(function () {
    return "<h2>" + vm.firstName() + "</h2>" +
        "<span>" + vm.address() + "</span>";
});

ko.applyBindings(vm);

注意:在两个小提琴中,我已经重构了一些东西 - 主要是为了简化