0

我正在尝试解决在另一个模板的上下文中渲染一个模板的问题。外部模板不知道也不应该关心内部模板及其视图模型。它只关心它自己的模板,一个嵌入内部模板的地方,传递它的名称和它的视图模型。

所以理想情况下,我希望我知道如何实现以下绑定:

<script type="text/html" id="outerTemplate">
    <div class="outer-template" data-bind="here: {}"></div>
</script>

<!-- ko nested: { to: 'outerTemplate', data: { name: 'I am an inner view model' } } -->

    <div class="inner-template" data-bind="text: name"></div>

<!-- /ko -->

如果有人对淘汰赛有足够的了解,可以轻松地勾勒出这种绑定,我将不胜感激。

更新:提出了功能请求:https ://github.com/knockout/knockout/issues/1251

4

2 回答 2

1

绑定允许您动态选择要使用的template模板名称,因此您可以执行以下操作:

<script id="outer" type="text/html">
    <h2>Outer</h2>
    <div data-bind="template: { name: tmplName, data: data }"></div>
</script>

<script id="inner" type="text/html">
    <h3>Inner</h3>
    <input data-bind="value: name" />
</script>

<div data-bind="template: 'outer'"></div>

在这种情况下,视图模型看起来像:

var vm = {
    tmplName: 'inner',
    data: {
        name: ko.observable("Bob")   
    }
};

ko.applyBindings(vm);

视图模型可以根据您的需要进行结构化。关键是您将模板名称和数据传递到模板绑定中。

示例:http: //jsfiddle.net/rniemeyer/LHhc8/

于 2013-02-14T19:13:48.253 回答
0

我自己做了一个工作示例:http: //jsfiddle.net/m34wp/4/

var templateComputedDomDataKey = '__ko__templateComputedDomDataKey__';
function disposeOldComputedAndStoreNewOne(element, newComputed) {
    var oldComputed = ko.utils.domData.get(element, templateComputedDomDataKey);
    if(oldComputed && (typeof (oldComputed.dispose) == 'function')) {
        oldComputed.dispose();
    }
    ko.utils.domData.set(element, templateComputedDomDataKey, (newComputed && newComputed.isActive()) ? newComputed : undefined);
}
function makeArray(arrayLikeObject) {
    var result = [];
    for(var i = 0, j = arrayLikeObject.length; i < j; i++) {
        result.push(arrayLikeObject[i]);
    }
    ;
    return result;
}
function moveCleanedNodesToContainerElement(nodes) {
    var nodesArray = makeArray(nodes);
    var container = document.createElement('div');
    for(var i = 0, j = nodesArray.length; i < j; i++) {
        container.appendChild(ko.cleanNode(nodesArray[i]));
    }
    return container;
}
ko.bindingHandlers['nested'] = {
    'init': function (element, valueAccessor) {
        var elementType = 1;
        var commentType = 8;
        var bindingValue = ko.utils.unwrapObservable(valueAccessor());
        if(element.nodeType == elementType || element.nodeType == commentType) {
            // It's an anonymous template - store the element contents, then clear the element
            var templateNodes = element.nodeType == 1 ? element.childNodes : ko.virtualElements.childNodes(element);
            var container = moveCleanedNodesToContainerElement(templateNodes);
            new ko.templateSources.anonymousTemplate(element)['nodes'](container);
        }
        return {
            'controlsDescendantBindings': true
        };
    },
    'update': function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var options = ko.utils.unwrapObservable(valueAccessor());
        var outerTemplateName = options['to'];
        var dataValue = ko.utils.unwrapObservable(options['data']) || viewModel;
        var innerContext = bindingContext['createChildContext'](dataValue);
        innerContext.innerTemplateElement = element;
        var templateComputed = ko.renderTemplate(outerTemplateName, innerContext, options, element);
        disposeOldComputedAndStoreNewOne(element, templateComputed);
    }
};
ko.bindingHandlers['here'] = {
    'init': function (element, valueAccessor) {
        return {
            'controlsDescendantBindings': true
        };
    },
    'update': function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var templateElement = bindingContext.innerTemplateElement;
        if(viewModel != null) {
            var innerContext = bindingContext['createChildContext'](viewModel);
            var templateComputed = ko.renderTemplate(templateElement, innerContext, {
            }, element);
            disposeOldComputedAndStoreNewOne(element, templateComputed);
        } else {
        }
    }
};
ko.virtualElements.allowedBindings['nested'] = true;
于 2013-02-15T12:09:23.157 回答