模板绑定更改时模板不会更改

时间:2013-10-17 16:27:32

标签: knockout.js

我有一个页面,我想更改哪个模板用于显示项目列表(例如简单视图和高级视图)。示例代码:

<script type="text/html" id="template1">
    Template 1
</script>

<script type="text/html" id="template2">
    Template 2
</script>

<input type="checkbox" data-bind="checked: viewSelect"/>
<button data-bind="click: newArray">Refresh Array</button>
<ul data-bind="template:{name: templateBinding, foreach: items}">
</ul>

JS:

var ViewModel = function(){
    var self = this;

    this.viewSelect = ko.observable();

    this.newArray = function(){
        console.log("newArray");
        self.items([{text:"Item1"},{text:"Item2"},{text:"Item3"}]);
    };

    this.templateBinding = ko.computed(function(){
        console.log("templateBinding");
        if(self.viewSelect()){
            return "template1";
        } else{
            return "template2";
        }
    });

    this.items = ko.observableArray([{text:"Item1"},{text:"Item2"},{text:"Item3"}]);
};

ko.applyBindings(new ViewModel());

我已使用此代码创建了a fiddle

以下是发生的事情:我希望Knockout在模板更改时重新创建显示的列表。挂起computed的{​​{1}}被调用(这可以从控制台确认),但模板不会更改,切换复选框不会更改显示。但是,对阵列内容的更改会使用新模板刷新列表。

有没有一种优雅的方式来做这件事,或者我做错了什么?

1 个答案:

答案 0 :(得分:2)

在foreach中为项目使用动态模板名称时,您需要指定要执行的函数。这将为每个项目调用(并将作为第一个arg传递该项目)。

因此,您可以将当前代码更改为:

this.getTemplate = function(){
    if(self.viewSelect()){
        return "template1";
    } else{
        return "template2";
    }
};

并绑定如:

<ul data-bind="template:{name: getTemplate, foreach: items}">

这是一个更新的小提琴:http://jsfiddle.net/rniemeyer/qAEXh/