95

I constantly find myself using this idiom in KO-based HTML templates:

<!-- ko if: isEdit -->
<td><input type="text" name="email" data-bind="value: email" /></td>
<!-- /ko -->
<!-- ko ifnot: isEdit -->
<td data-bind="text: email"></td>
<!-- /ko -->

Is there a better/cleaner way to do conditionals in KO, or is there a better approach than just using traditional if-else constructs?

Also, I would just like to point out that some versions of Internet Explorer (IE 8/9) don't parse the above example correctly. Please see this SO question for more information. The quick summary is, don't use comments (virtual bindings) inside table tags to support IE. Use the tbody instead:

<tbody data-bind="if: display"><tr><td>hello</td></tr></tbody>
Community
  • 1
  • 1
Jensen Ching
  • 3,144
  • 4
  • 26
  • 42

4 Answers4

64

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.

Dan F
  • 11,958
  • 3
  • 48
  • 72
RP Niemeyer
  • 114,592
  • 18
  • 291
  • 211
  • strange, my HTML won't show up. Also just noticed that Michael gave pretty much the same answer. – RP Niemeyer Jul 19 '12 at 05:12
  • Thanks for a comprehensive list of options. I guess my original code style works for simple cases. I'll check out the other options when the need arises. – Jensen Ching Jul 19 '12 at 06:26
  • is there a way to customize the template even more, such as "template: data, proppertyName: 'email'" and in the template data-bind="text: $data[propertyName]". – Onur Topal Apr 05 '14 at 11:04
  • @OnurTOPAL - yes as long as you have a variable `propertyName`, you can dynamically determine the template name. – RP Niemeyer Apr 05 '14 at 13:25
44

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 -->
Michael Best
  • 16,623
  • 1
  • 37
  • 70
4

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 -->
Dmitry Komin
  • 549
  • 6
  • 7
2

There is now also the knockout-else binding/plugin (that I wrote to address this issue).

Brian M. Hunt
  • 81,008
  • 74
  • 230
  • 343
  • is it possible to use knockout-else with KSB? If yes then how to use that? your answer will be appreciate. Thanks for make libraries like KSB. – Narendra Solanki Feb 04 '21 at 18:39