本文介绍了淘汰赛 Twitter Bootstrap 弹出框绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为引用模板的 twitter boostrap 弹出框创建自定义绑定,但在创建弹出框后,我无法处理弹出框内内容的绑定部分.

我之前看到过这个问题,但我觉得它们大多非常混乱,而且我非常接近一个可重复使用的解决方案,该解决方案以我想要的方式使用模板.

http://jsfiddle.net/billpull/Edptd/

//绑定推特弹出框ko.bindingHandlers.popover = {初始化:函数(元素,valueAccessor,allBindingsAccessor,viewModel,bindingContext){var tmplId = ko.utils.unwrapObservable(valueAccessor());var tmplHtml = $('#' + tmplId).html();var uuid = guid();var domId = "ko-bs-popover-" + uuid;var tmplDom = $('

', {"class" : "ko-popover","id" : domId}).html(tmplHtml);选项 = {内容:tmplDom[0].outerHTML};var popoverOptions = ko.utils.extend(ko.bindingHandlers.popover.options, options);控制台日志($(元素));控制台日志(元素);$(element).bind('click', function () {$(this).popover(popoverOptions).popover('toggle');ko.applyBindings(bindingContext, document.getElementById(domId));});},选项: {位置:正确",标题: "",html:对,内容: "",触发器:手动"}};

===编辑

根据下面的答案更新了代码,无需额外的 withProperties 绑定

//绑定推特弹出框ko.bindingHandlers.popover = {初始化:函数(元素,valueAccessor,allBindingsAccessor,viewModel,bindingContext){//读取弹出选项var popoverBindingValues = ko.utils.unwrapObservable(valueAccessor());//设置popover模板idvar tmplId = popoverBindingValues.template;//设置弹出触发var trigger = popoverBindingValues.trigger;//获取模板htmlvar tmplHtml = $('#' + tmplId).html();//创建要绑定到的唯一标识符var uuid = guid();var domId = "ko-bs-popover-" + uuid;//创建正确的绑定上下文var childBindingContext = bindingContext.createChildContext(viewModel);//创建用于弹出内容的 DOM 对象var tmplDom = $('

', {"class" : "ko-popover","id" : domId}).html(tmplHtml);//设置内容选项选项 = {内容:tmplDom[0].outerHTML};//需要复制这个,否则所有的弹窗都以最后一项的值结束var popoverOptions = $.extend({}, ko.bindingHandlers.popover.options);popoverOptions.content = options.content;//将弹出框绑定到元素点击$(element).bind(trigger, function () {$(this).popover(popoverOptions).popover('toggle');//如果弹出框可见,则将视图模型绑定到我们的 dom IDif($('#' + domId).is(':visible')){ko.applyBindingsToDescendants(childBindingContext, $('#' + domId)[0]);}});返回 { controlDescendantBindings: true };},选项: {位置:正确",标题: "",html:对,内容: "",触发器:手动"}};
解决方案

你需要使用我的老朋友 自定义绑定.

ko.bindingHandlers.withProperties = {初始化:函数(元素,valueAccessor,allBindingsAccessor,viewModel,bindingContext){//使用额外的属性创建一个修改后的绑定上下文,并将其应用于后代元素var newProperties = valueAccessor(),innerBindingContext = bindingContext.extend(newProperties);ko.applyBindingsToDescendants(innerBindingContext, element);//同时告诉KO *不要*绑定后代本身,否则他们将被绑定两次返回 { controlDescendantBindings: true };}};

然后你需要在你生成的 html 中添加一个 data-bind 属性:

 var tmplDom = $('

', {"class": "ko-popover",id":domId,"data-bind": "withProperties: { label: '" + viewModel.label() + "', required: '" + viewModel.required() + "' }"

我整理了一个 jsFiddle 来展示这一点.有几个问题,我必须为每个弹出框复制弹出框选项,否则它们都会以最后一组值结束.

 var popoverOptions = $.extend({}, ko.bindingHandlers.popover.options);popoverOptions.content = options.content;

而且我还必须将绑定应用到弹出窗口,如果它可见,否则它似乎试图绑定到整个页面.

$(element).bind('click', function () {$(this).popover(popoverOptions).popover('toggle');//如果在弹出窗口不可见时应用它,我认为它会尝试绑定到整个页面并抛出错误if($('#' + domId).is(':visible')){ko.applyBindings(viewModel, $('#' + domId)[0]);}});

这似乎也是 2-way,因为您可以更改弹出窗口中的值并更新非弹出元素,但我不会撒谎,我没想到会发生这种情况!

I am trying to create a custom binding for twitter boostrap popovers that references a template but I am having trouble with the binding part of the content inside of the popover once it has been created.

I have seen this question asked before but I feel like they were mostly pretty messy and I am pretty close to a reusable solution that uses templates how I want to.

http://jsfiddle.net/billpull/Edptd/

// Bind Twitter Popover
ko.bindingHandlers.popover = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var tmplId = ko.utils.unwrapObservable(valueAccessor());
        var tmplHtml = $('#' + tmplId).html();
        var uuid = guid();
        var domId = "ko-bs-popover-" + uuid;
        var tmplDom = $('<div/>', {
            "class" : "ko-popover",
            "id" : domId
        }).html(tmplHtml);

        options = {
            content: tmplDom[0].outerHTML
        };

        var popoverOptions = ko.utils.extend(ko.bindingHandlers.popover.options, options);

        console.log($(element));
        console.log(element);

        $(element).bind('click', function () {
            $(this).popover(popoverOptions).popover('toggle');
            ko.applyBindings(bindingContext, document.getElementById(domId));
        });
    },
    options: {
        placement: "right",
        title: "",
        html: true,
        content: "",
        trigger: "manual"
    }
};

===EDIT

Updated code based on answer below that allows you to do it without the extra withProperties binding

// Bind Twitter Popover
ko.bindingHandlers.popover = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        // read popover options
        var popoverBindingValues = ko.utils.unwrapObservable(valueAccessor());

        // set popover template id
        var tmplId = popoverBindingValues.template;

        // set popover trigger
        var trigger = popoverBindingValues.trigger;

        // get template html
        var tmplHtml = $('#' + tmplId).html();

        // create unique identifier to bind to
        var uuid = guid();
        var domId = "ko-bs-popover-" + uuid;

        // create correct binding context
        var childBindingContext = bindingContext.createChildContext(viewModel);

        // create DOM object to use for popover content
        var tmplDom = $('<div/>', {
            "class" : "ko-popover",
            "id" : domId
        }).html(tmplHtml);

        // set content options
        options = {
            content: tmplDom[0].outerHTML
        };

        // Need to copy this, otherwise all the popups end up with the value of the last item
        var popoverOptions = $.extend({}, ko.bindingHandlers.popover.options);
        popoverOptions.content = options.content;

        // bind popover to element click
        $(element).bind(trigger, function () {
            $(this).popover(popoverOptions).popover('toggle');

            // if the popover is visible bind the view model to our dom ID
            if($('#' + domId).is(':visible')){
                ko.applyBindingsToDescendants(childBindingContext, $('#' + domId)[0]);
            }
        });

        return { controlsDescendantBindings: true };
    },
    options: {
        placement: "right",
        title: "",
        html: true,
        content: "",
        trigger: "manual"
    }
};
解决方案

You need to use my old friend, custom bindings.

ko.bindingHandlers.withProperties = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        // Make a modified binding context, with a extra properties, and apply it to descendant elements
        var newProperties = valueAccessor(),
            innerBindingContext = bindingContext.extend(newProperties);
        ko.applyBindingsToDescendants(innerBindingContext, element);

        // Also tell KO *not* to bind the descendants itself, otherwise they will be bound twice
        return { controlsDescendantBindings: true };
    }
};

You then need to add a data-bind attribute to the html you are generating:

    var tmplDom = $('<div/>', {
        "class": "ko-popover",
        "id": domId,
        "data-bind": "withProperties: { label: '" + viewModel.label() + "', required: '" + viewModel.required() + "' }"

I've put together a jsFiddle showing this. There were a couple of gotchas, I had to copy the popover options for each popover, otherwise they all ended up with the last set of values.

    var popoverOptions = $.extend({}, ko.bindingHandlers.popover.options);
    popoverOptions.content = options.content;

And I also had to apply binding to the popup only if it is visible, otherwise it appears to attempt to bind to the whole page.

$(element).bind('click', function () {
            $(this).popover(popoverOptions).popover('toggle');
            // If you apply this when the popup isn't visible, I think that it tries to bind to thewhole pageand throws an error
            if($('#' + domId).is(':visible'))
            {
                ko.applyBindings(viewModel, $('#' + domId)[0]);
            }
        });

This also appears to be 2-way, in that you can change the values in the popup and it updates the non-popup elements, but I won't lie, I didn't expect that to happen!

这篇关于淘汰赛 Twitter Bootstrap 弹出框绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-18 00:08
查看更多