Bootstrap's tooltip not working with knockout bindings? (w fiddle)
Asked Answered
D

4

26

Fiddle: http://jsfiddle.net/LkqTU/9399/

Code:

var ViewModel = function (first, last) {
    var self = this;
    self.showIcon = ko.observable(false);
    self.triggerIcon = function () {
        self.showIcon(true);
    };
};
$('.card-delete-button').tooltip({
    'placement': 'top',
        'title': 'Text'
});
ko.applyBindings(new ViewModel("Planet", "Earth"));

For some reason the tooltip isn't showing up for the '.card-delete-button'. I think it's because that DOM element isn't available until the triggerIcon function is hit. But in application, I have to bind these tooltips to a lot of different elements and would prefer to do it once, in one place, instead of sticking the binding into the triggerIcon function. how can this be achieved?

Disassemble answered 1/6, 2013 at 18:15 Comment(0)
R
61

Your best bet in a situation like this is to create a custom binding that you can use to place tooltips anywhere in the markup.

Here is one implementation of a tooltip binding:

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

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

        $(element).tooltip(options);

        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            $(element).tooltip("destroy");
        });
    },
    options: {
        placement: "right",
        trigger: "click"
    }
};

You would then use this binding on your page like:

<input data-bind="value: name, tooltip: { title: help, trigger: 'hover' }" />

You can set options globally and then override them with whatever you pass into the binding.

When you get into templating and control-flow scenarios, using a custom binding really helps, because it will automatically get initialized (and cleaned up) at the right time without needing to manually know when to call code.

Here is a sample: http://jsfiddle.net/rniemeyer/BF5yW/

Ratafia answered 1/6, 2013 at 18:39 Comment(1)
options: { container: 'body' } is important for tooltip widthArium
T
7

Addendum to @RP Niemeyer's answer...

On github there is a small project called Knockout-Bootstrap for making "rich two way interactions with Bootstrap and Knockout bindings".

Below is a fork of your fiddle that includes Knockout-Bootstrap.

http://jsfiddle.net/qZkXP/

<div class='liveExample' data-bind="event: {mouseover: triggerIcon}">   
    <!-- ko if: showIcon -->
    <a class="card-delete-button" 
       data-bind="tooltip: {title: 'Another tooltip', placement: 'right'}">
           <i class="icon-trash"></i>
    </a>
    <!-- /ko -->
</div>
Tinct answered 1/6, 2013 at 18:55 Comment(0)
T
4

I also encountered some problems regarding the tooltip binding with knockout and the answer offered by RP Niemeyer helped me. But then, when I tried to bind to a function which returns the options object of the tooltip, that wasn't called (it has been called only once). So it was not working if I was trying to dynamically change the title of the tooltip, based on the mapped css classes. So, the solution I found is:

ko.bindingHandlers["tooltip"] = {
'init': function (element, valueAccessor) {
    var local = ko.utils.unwrapObservable(valueAccessor());
    var options = {};

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

    $(element).tooltip(options);

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

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

    $(element).data("bs.tooltip").options.title = options.title;
},
options: {
    placement: "top",
    trigger: "click"
}};

I wanted to make this remark here because I think it would be useful in those cases when the title of the tooltip has to be changed dynamically.

Terminator answered 16/12, 2015 at 11:25 Comment(0)
N
0

The answer provided by Adi Mihasan almost worked for me. I had to make the following changes, which may also help others.

$(element).tooltip("destroy");

to

$(element).tooltip("dispose");

AND

$(element).data("bs.tooltip").options.title = options.title 

to

$(element).data("bs.tooltip").config.title = options.title
Naval answered 7/10, 2019 at 13:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.