【问题标题】:Custom KnockoutJS bindingHandler for dynamic Bootstrap Tooltips用于动态引导工具提示的自定义 KnockoutJS bindingHandler
【发布时间】:2014-01-01 09:10:15
【问题描述】:

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

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

我创建了一个新的JSFiddle,其中包含以下基于先前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,但我不太确定。

有什么想法吗?我会继续更新这个,因为动态引导工具提示似乎是一个常见的想法。

【问题讨论】:

    标签: javascript jquery twitter-bootstrap knockout.js


    【解决方案1】:

    问题的根源在于更新绑定没有触发,因为它不依赖于您尝试更新的属性(即名字和地址);

    通常,您可以将这些属性委托给新绑定,并让敲除自动处理依赖关系跟踪。但是,在这种情况下,您实际上返回的是一个字符串,因此无法使用元素的自动绑定。字符串是必需的,因为这就是工具提示的工作方式。如果它可以动态地从 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);
    

    注意:在这两个小提琴中,我都稍微重构了一下——主要是为了简化

    【讨论】:

    • 谢谢,我更喜欢 v1,因为我试图将 DOM 排除在 VM 之外。特别是因为我的真实示例,没有稀释到 firstName 和 address 属性相当大。
    • 我想强调您跟踪属性的解决方案很好。我试图在自定义 bindingHandler 中做类似的事情,但被卡住了。
    • 我有一个新的 JSFiddle:jsfiddle.net/tMbs5/14,它将表明名称实际上可以在连续的数据绑定操作中发生变化。
    猜你喜欢
    • 1970-01-01
    • 2012-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-12
    • 1970-01-01
    相关资源
    最近更新 更多