How to template If-Else structures in data-bound views?
There are a couple different ways that you can handle this type of code.
with an if/ifnot combination like you are now. This works fine and is not terribly verbose.
Michael Best's switch/case binding (https://github.com/mbest/knockout-switch-case) is quite flexible and can let you easily handle this and more complicated ones (more states than true/false).
Another option is to use dynamic templates. You would bind an area to one or more templates with the template name being used based on an observable. Here is a post that I wrote on this topic a while back: http://www.knockmeout.net/2011/03/quick-tip-dynamically-changing.html. In your scenario, it might look like:
<td data-bind="template: $root.getCellTemplate"></td><script id="cellEditTmpl" type="text/html"> <input type="text" name="email" data-bind="value: email" /></script><script id="cellTmpl" type="text/html"> <span data-bind="text: email"></span></script>
The getCellTemplate
function could live wherever, but would be given the item ($data) as the first argument and would return the name of the template to use.
One approach is to use named templates (which can support passing arguments):
<!-- ko template: isEdit() ? 'emailEdit' : 'emailDisplay' --><!-- /ko --><script id="emailEdit" type="text/html"> <td><input type="text" name="email" data-bind="value: email" /></td></script><script id="emailDisplay" type="text/html"> <td data-bind="text: email"></td></script>
Another option is use my switch/case plugin, which would work like this:
<!-- ko switch --> <!-- ko case: isEdit --> <td><input type="text" name="email" data-bind="value: email" /></td> <!-- /ko --> <!-- ko case: $else --> <td data-bind="text: email"></td> <!-- /ko --><!-- /ko -->
To avoid recalculation of knockout binding when using combination of if: / ifnot: you can use them in conjunction with 'with:' construction
<!-- ko with: $data.DoSomePerformanceCriticalWork($data.SomeParameter()) --> <!-- ko if: $data.Condition() --> ... some markup ... <!-- /ko --> <!-- ko ifnot: $data.Condition() --> ... some markup ... <!-- /ko --> <!-- /ko -->