使用Knockout绑定返回字符串

时间:2015-03-27 11:34:08

标签: javascript knockout.js

我试图使用Knockout来使用无限滚动插件,我使用的更好一些,但是如何绑定它却苦苦挣扎。不确定它是否可能以当前形式出现。

滚动器调用数据函数,该函数通过AJAX加载下一个数据块。然后它调用一个将该数据转换为HTML的工厂函数,然后将HTML加载到容器中,并更新其当前内容大小的内部状态。

我坚持认为它需要一个HTML字符串。

我想做的是:

<div class="scroller" data-bind="infiniteScroll: { get: loadItems }">
    <div class="item">
        <p>
            <span data-bind="text:page"></span>
            <span class="info" data-bind="text"></span>
        </p>
    </div>
</div>

我的绑定,我完全坚持,就是这个 - 目前只是硬编码响应,显然 - 我需要用模板绑定替换它:

ko.bindingHandlers.infiniteScroll = {
    init: 
        function(el, f_valueaccessor, allbindings, viewmodel, bindingcontext) 
        {
            if($.fn.infiniteScroll)
            {
                // Get current value of supplied value
                var field = f_valueaccessor();
                var val = ko.unwrap(field);

                var options = {};

                if(typeof(val.get) == 'function')
                    options = val;
                else
                    options.get = val;

                options.elementFactory = options.elementFactory || 
                    function(contentdata, obj, config)
                    {
                        var s = '';

                        for(var i = 0; i < contentdata.length; i++)                         
                        {
                            var o = contentdata[i];

                            // NEED TO REPLACE THIS
                            s += '<div class="item"><p>Item ' + o.page + '.' + i + ' <span class="info">' + o.text + '</span></p></div>';
                        }

                        return s;
                    };

                $(el).infiniteScroll(options);

                return { controlsDescendantBindings: true };
            }
        }
};

contentdata是一个对象数组,例如[ { page:1, text:'Item1' }, { page:1, text:'Item2' } ... ]

不同来电之间的网页尺寸可能不同;我无法知道服务会返回什么;它不是传统的页面,更多地将其视为下一个数据块。

所以在元素工厂中我想以某种方式使用.scroller中的标记作为模板绑定contentdata数组,类似于foreach,然后将该标记返回到滚动插件。

请注意,我可以修改无限卷轴源,所以如果不能用字符串完成,返回DOM元素也没问题。

我只是不知道如何a)将内容用作模板,b)将绑定结果返回给插件,以便更新其状态。

注意:我最终打算使用它的页面目前在非平凡对象模型上使用foreach;因此需要使用相同的标记;它需要几乎是替代品。

1 个答案:

答案 0 :(得分:0)

我实际上已经知道如何使用现有的滚动条来完成这个问题:Jquery knockout: Render template in-memory

基本上,您使用applyBindingsToNode(domelement, bindings),它将KO绑定应用于节点集,重要的是不必连接到DOM。

所以我可以将绑定元素的标记存储为模板,然后将其清空,然后对于元素工厂,使用jQuery创建临时节点集,使用上面的函数绑定它,然后返回HTML。

不可否认,使用纯KO滚动器重构可能会更好,但这意味着我可以继续使用经过测试和熟悉的插件,代码可能会帮助人们,因为这似乎是一个非常常见的问题主题。

以下是绑定的新代码(标记如上)。

ko.bindingHandlers.infiniteScroll = {
    init: 
        function(el, f_valueaccessor, allbindings, viewmodel, bindingcontext) 
        {
            if($.fn.infiniteScroll)
            {
                // Get current value of supplied value
                var field = f_valueaccessor();
                var val = ko.unwrap(field);

                var options = {};

                if(typeof(val.get) == 'function')
                    options = val;
                else
                    options.get = val;

                var template = $(el).html();

                options.elementFactory = options.elementFactory || 
                    function(contentdata, obj, config)
                    {
                        // Need a root element for foreach to use as a container, as it removes the root element on binding.
                        var newnodes = $('<div>' + template + '</div>');

                        ko.applyBindingsToNode(newnodes[0], { foreach: contentdata });

                        return newnodes.html();                         
                    };

                $(el)
                    .empty()                
                    .infiniteScroll(options);

                return { controlsDescendantBindings: true };
            }
        }
};