7

Can anyone explain me what is wrong with my view model or template in this example jsfiddle?

It doesn't work as expected. Basically the view model contains an object and that object is null. In the view, there is a template binding to this object. As this object is null, it shouldn't render the template. However, it does try to render the template and fails in my example. If job object is null then I don't want to render the template.

According to this article by Ryan, if a viewmodel contains a null object and there is a "template binding" for this object, it won't render the template.

Here is my view model:

var job = function(title) {
    this.jobTitle = ko.observable(title);
}

var ViewModel = function(first, last) {
    this.firstName = ko.observable(first);
    this.lastName = ko.observable(last);
    //this.job = ko.observable(new job("software developer"));
    this.job = ko.observable(null);

    this.fullName = ko.computed(function() {
        return this.firstName() + " " + this.lastName();
    }, this);
};

ko.applyBindings(new ViewModel("FirstName", "LastName")); 

And this is the view:

<div class='liveExample'>   
    <p>First name: <input data-bind='value: firstName' /></p> 
    <p>Last name: <input data-bind='value: lastName' /></p> 
    <p data-bind="template: { name: 'editorTmpl', data: job }"></p>
    <h2>Hello, <span data-bind='text: fullName'> </span>!</h2>  
</div>

<script id="editorTmpl" type="text/html">
    Job: <input data-bind='value: jobTitle' />
</script>

2 Answers 2

8

The linked artifice was written almost 3 years ago. By the time the latest version of Knockout was around 1.2.1.

And in Knockout 1.2.1 your code is working fine: Demo using KO 1.2.1

However since then Knockout has changed a lot so it is not supporting this behavior anymore.

Nowadays you need to use the if option of the template binding

<p data-bind="template: { name: 'editorTmpl', if: job, data: job}"></p>

Demo JSFiddle.

Or the with (if) binding to achieve the same outcome:

<div class='liveExample'>   
    <p>First name: <input data-bind='value: firstName' /></p> 
    <p>Last name: <input data-bind='value: lastName' /></p> 
    <!-- ko with: job -->
        <p data-bind="template: { name: 'editorTmpl'}"></p>
    <!-- /ko -->
    <h2>Hello, <span data-bind='text: fullName'> </span>!</h2>  
</div>

Demo JSFiddle.

Sign up to request clarification or add additional context in comments.

5 Comments

Although what you say is try, this is a fiddle with Ryan's example and ko 3.0. It works just fine: jsfiddle.net/z54Ag
@GôTô no it is not working fine... the li gets rendered with a result in it, altough the selectedItem in null...
Well yes, but at least it does not throw an error. Any idea why one throws an error and not the other?
It is not throwing an error because of the property name: name which was used in the binding (I guess in this sample a fuction was used as a bindingcontext and every fuction has a name property). If you use a different property name it will throw an error: jsfiddle.net/z54Ag/1
Indeed, thanks for taking the time to point that out (jsfiddle.net/z54Ag/2)
3

You could surround your template binding with a div which uses the 'if' data-binding to the job observable:

<div data-bind="if: job">
    <p data-bind="template: { name: 'editorTmpl', data: job }"></p>
</div>

The editor template is hidden when job is null, and visible when not null.

EDIT:

A better solution is to pass the 'if' option to the template binding:

<p data-bind="template: { if: job, name: 'editorTmpl', data: job }"></p>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.