0

In the example below you'll see that doSomething never fires. If you remove the if: Comments from the templating binding doSomething will fire as expected. Does anyone know what is happening to cause this? This also occurs while using the data attribute on the template binding handler.

I am currently using Knockout 2.2.1. jsfiddle http://jsfiddle.net/YADzx/2/

<div data-bind="template: { if: Comments, name: 'comments' }"></div> <script type="tmpl" id="comments"> <div data-bind="foreach: { data: Comments, afterAdd: $root.doSomething }"> <div data-bind="text: name"></div> </div> </script> <script> var vm = { Comments: ko.observableArray([{name:'hey'}]), doSomething: function (element, index, data) { $(element).addClass('wow'); } }; ko.applyBindings(vm); vm.Comments.push({name:'foo'}); vm.Comments.push({name:'bar'}); </script> 

1 Answer 1

10

The if condition on the template binding causes it to update whenever Comments changes. Knockout will then re-render the entire template and the previous state of the foreach binding is lost.

There are a few ways to work around this depending on what side-effects you want or don't want.

  1. Remove the if option. Your code will all still work, but you'll have the <div> with the foreach binding in your HTML. So this isn't a good option if it messes up your layout.

  2. Split up the if from the template and use another element (or comment-syntax) with the if binding. This will work as long as you're using version 2.2.0 or higher of Knockout.

    <script type="tmpl" id="comments"> <!--ko if: Comments--> <div data-bind="foreach: { data: Comments, afterAdd: $root.doSomething }"> <div data-bind="text: name"></div> </div> <!--/ko--> </script> 
  3. Instead of using the if binding, use the visible binding, which hides the current element and does not re-render.

    <script type="tmpl" id="comments"> <div data-bind="visible: Comments, foreach: { data: Comments, afterAdd: $root.doSomething }"> <div data-bind="text: name"></div> </div> </script> 

One thing to consider, though, is that an observableArray won't generally contain a falsy value. That's because in JavaScript, an empty array is still truthy. If you want to test for an empty array, you'll need to change from if: Comments to if: Comments().length.

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

1 Comment

Thank you so much, wish I could vote this up more.. spent hours trying to figure this out!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.