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>
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.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With