在Knockout.js中两次绑定一个自定义处理程序 [英] Binding a custom handler twice in knockoutjs

查看:57
本文介绍了在Knockout.js中两次绑定一个自定义处理程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个自定义绑定处理程序,以显示淘汰赛中的自举弹出窗口:

I've written a custom binding handler to show a bootstrap popover in knockout:

ko.bindingHandlers.popover = {
    init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {

        $(element).popover({
            html: true,
            content: function () { return $('#' + ko.unwrap(valueAccessor().template)).html(); },
            placement: "right",
            trigger: "manual",
            container: 'body'
        });

    },
    update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {

        if (valueAccessor().visible()) {
            $(element).popover('show');
            var popover = $("body .popover").last().get(0);
            ko.cleanNode(popover);
            ko.applyBindings(bindingContext.$rawData, popover);

        } else
            $(element).popover('hide');
    }
};

...效果很好.

但是,当我尝试在相同的元素上将它两次绑定时:

However, when I try to bind it twice on the same element like this:

<input type="password" class="form-control" id="login-password" placeholder="Password" data-bind="textInput: login.password.input, hasFocus: login.password.focus, popover: { visible: login.showBadPassword, placement: 'right', template: 'bad-password-popover' }, popover: { visible: login.showThrottled, placement: 'right', template: 'throttled-popover' }" />

...它仅绑定第二个.我猜这是因为它覆盖了第一个.

...it only binds the second one. I'm guessing this is because it's overwriting the first one.

是否可以将同一事物绑定两次?

Is there a way to bind the same thing twice?

推荐答案

有一个基本问题,即一次只能显示一个弹出窗口.您可以使用一些在单个元素中支持多个弹出框的技术,但这不是标准的方法.

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" rel="stylesheet"/>
<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>

在此示例实现中,您可以指定几种不同的弹出框配置,但是可见的将是第一个可见的为true的窗口.您可以通过虚拟方式修改此脚本:

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:

  • 在同一弹出窗口中包含多个div,并使用不同的可见可观察对象控制它们的可见性.这应该在init中完成,并且update中的代码应停止销毁并重新创建弹出窗口
  • 使用一些可用的技术在同一元素中显示多个弹出框
  • 忘记此实现,并在每个原始popvoer中使用不可见元素
  • 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

这篇关于在Knockout.js中两次绑定一个自定义处理程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆