Skip to content Skip to sidebar Skip to footer

Binding A Custom Handler Twice In Knockoutjs

I've written a custom binding handler to show a bootstrap popover in knockout: ko.bindingHandlers.popover = { init: function (element, valueAccessor, allBindings, viewModel, bi

Solution 1:

There is one basic problem, which is that you can only show one popover at a time. You could use some technique to support more than one popover in a single element, but that's not standard.

If you take into account this limitation of only being able to see one popover at a time, you can use a custom binding handler like this:

ko.bindingHandlers.popover = {
    init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
    },
    update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
		var values = ko.unwrap(valueAccessor());
        values.forEach(function(value) { value.visible(); });
        debugger;
        var visibleValue = values.find(function(value) { return value.visible();});
        
        if (visibleValue) {
            $(element).popover('destroy');
            $(element).popover({
                html: true,
                content:  $('#' + ko.unwrap(visibleValue.template)).html(),
                placement: ko.unwrap(visibleValue.placement),
                container: 'body'
            });
            $(element).popover('show');
            var popover = $("body .popover").last().get(0);
            ko.cleanNode(popover);
            ko.applyBindings(bindingContext.$rawData, popover);
        } else {
            $(element).popover('hide');
        };
    }
};

var vm = {
    triggerA: ko.observable(),
    triggerB: ko.observable()
}

ko.applyBindings(vm);
<link href="https://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<input type="password"  
       data-bind="popover: 
                  [{visible: triggerA, placement: 'right', template: 'A'},
                  {visible: triggerB, placement: 'right', template: 'B'}]"/>

<script type="text/html" id="A">
    This is popover <b>A</b>
</script>
<script type="text/html" id="B">
    This is popover <b>B</b>
</script>
<br/>
<label>Trigger A<input type="checkbox" name="triggers" data-bind="checked: triggerA"></label>
<label>Trigger B<input type="checkbox" name="triggers" data-bind="checked: triggerB"></label>

In this sample implementation you can specify several different popover configurations, but the visible one will be the first whose visible observable is true. You could modify this script in serveal ways:

  • include several divs in the same popover and control their visibility with the different visible observables. This should be done in the init, and the code in the update should stop destroying and recreating the popover
  • use some of the available techniques to show more than one popover in the same element
  • forget about this implementation, and use invisible elements with your original popvoer in each of them

Solution 2:

If you pass some "popoverId" as binding parameter, you can store certain popup in the data:

var newPopover = $(element).popover({ /* some potions */ });
$(element).data(ko.unwrap(valueAccessor().popoverId, newPopover);

in init and get the popover in update:

var popover = $(element).data(valueAccessor().popoverId);

Post a Comment for "Binding A Custom Handler Twice In Knockoutjs"