2012-10-31 28 views
2

我有一个问题,使用自定义模板绑定knockoutjs。knockoutjs - 自定义模板绑定父级内容

假设我有一个HTML的身体是这样的:

<div id="1"> 
    <div data-bind="template:{name: '2', data: data}"></div> 
</div> 

<div id="2"> 
    <h3 data-bind="text: caption"></h3> 
</div> 

JS代码如下所示:

var ViewModel2 = function() { 
    this.caption = ko.observable("Caption"); 
} 

var ViewModel1 = function() { 
    this.data = new ViewModel2(); 
} 

ko.applyBindings(new ViewModel1(), document.getElementById("1")); 

如果我们测试此代码,一切都将工作得很好;
请参阅JSFiddle示例:http://jsfiddle.net/4eTWW/33/

现在假设我们想使自定义模板绑定。我们将使用'templatex'绑定而不是'template'。

在HTML我们需要改变的只是一条线:

<div data-bind="templatex:{name: '2', data: data}"></div> 

接下来,让我们添加自定义模板结合JS:

/*Custom binding*/ 
ko.bindingHandlers.templatex = { 
    init: function (element) { 
     ko.bindingHandlers.template.init.apply(this, arguments); 
    }, 

    update: ko.bindingHandlers.template.update 
} 

参见:http://jsfiddle.net/4eTWW/35/

但是,在这种情况下,我们有一个错误,说它无法在模型中找到'标题'。

现在让我们添加模板{}为HTML绑定:

<div data-bind="template: {}, templatex:{name: '2', data: data}"></div> 

参见:http://jsfiddle.net/4eTWW/36/

而现在一切都运行得很好。

看来,虽然绑定父div它不能确定子div是模板。

那么如何将其标记为我的自定义模板联编程序中的模板?

谢谢。

+1

你需要retu模板绑定'init'函数的值。它返回一个名为'controlsDescendantBindings'的标志,告诉KO你将处理绑定其子项。否则,它将继续尝试将子元素与当前数据上下文绑定。 –

回答

1

你错了更新处理,改成这样:

ko.bindingHandlers.templatex= { 
    init: function(element) { 
     // do things 
     return ko.bindingHandlers.template.init.apply(this, arguments); 
    }, 

    update: function(element) { 
     return ko.bindingHandlers.template.update.apply(this, arguments); 
    } 
} 

这里工作小提琴:http://jsfiddle.net/vyshniakov/4eTWW/39/

+0

以前的变体也可以使用,但它需要返回值。 – Zelzer

0

我不认为你可以使用自定义绑定来创建一个新的模板引擎。您需要注册您的定制引擎ko.setTemplateEngine()

从knockoutjs来源:

If you want to make a custom template engine, 

[1] Inherit from the ko.templateEngine class (like ko.nativeTemplateEngine does) 
[2] Override 'renderTemplateSource', supplying a function with this signature: 

     function (templateSource, bindingContext, options) { 
      // - templateSource.text() is the text of the template you should render 
      // - bindingContext.$data is the data you should pass into the template 
      // - you might also want to make bindingContext.$parent, bindingContext.$parents, 
      //  and bindingContext.$root available in the template too 
      // - options gives you access to any other properties set on "data-bind: { template: options }" 
      // 
      // Return value: an array of DOM nodes 
     } 

[3] Override 'createJavaScriptEvaluatorBlock', supplying a function with this signature: 

     function (script) { 
      // Return value: Whatever syntax means "Evaluate the JavaScript statement 'script' and output the result" 
      //    For example, the jquery.tmpl template engine converts 'someScript' to '${ someScript }' 
     } 

    This is only necessary if you want to allow data-bind attributes to reference arbitrary template variables. 
    If you don't want to allow that, you can set the property 'allowTemplateRewriting' to false (like ko.nativeTemplateEngine does) 
    and then you don't need to override 'createJavaScriptEvaluatorBlock'. 

实例:http://jsfiddle.net/6pStz/(见注7这个page