user3272018
user3272018

Reputation: 2419

Knockout best practices. If or visible

I'm looking for knockout if or visible best practices in this case:

<div data-bind="visible: $root.obsVar()">
    ...
    <input type="text" data-bind="value: $root.obsVar().someField" />
    ...
</div>

In case when $root.obsVar() is undefined, error will be thrown. If you change visible to if, problem will miss, but it requires rewriting of the html. If there is a lot of murkup in div, it takes a lot of time. Are there any reasons to change $root.obsVar().someField to $root.getSomeFieldValue that always returns correct value or undefined? Or maybe there are other techniques not to get overhead and avoid errors.

Upvotes: 15

Views: 8849

Answers (4)

Andrew
Andrew

Reputation: 20091

You might find you need to use both.

Use if to remove the markup from the DOM - preventing possible JS errors, and so it doesn't take up space on the page.

And then use visible to hide the element until the page is fully loaded.

<!-- ko if: whatever -->
<div data-bind="visible: true" style="display: none">
    my content
</div>
<!-- /ko -->

Upvotes: 2

JotaBe
JotaBe

Reputation: 39025

As stated in David Sherret's answer, the main difference is that with if the DOM elements disappear if the condition is not fulfilled, and with visible they're simply hidden, but are always present in the DOM tree.

The main consequence is that if you're using if and you have to handle events you'll have to use delegated events, or attach them everytime the elements are recreated. When you use KO you usually don't do event handling, because you use bindings like click which are handled by KO, and so you don't have this problem. But you can have some other frameworks involved, like validators, jQuery UI date pickers, and so on, which will have trouble to work correctly with KO's if.

Upvotes: 1

David Sherret
David Sherret

Reputation: 106660

It really depends on the scenario. From the docs:

if plays a similar role to the visible binding. The difference is that, with visible, the contained markup always remains in the DOM and always has its data-bind attributes applied - the visible binding just uses CSS to toggle the container element’s visiblity. The if binding, however, physically adds or removes the contained markup in your DOM, and only applies bindings to descendants if the expression is true.

In your scenario, the only way to prevent an error without using if, when someField is null, is to do something along these lines:

data-bind="value: ($root.obsVar() == null) ? null : $root.obsVar().someField"

That's really annoying to have to write each time you access a property. It makes the code harder to maintain and it makes it easier to make a mistake—especially when you're adding a new binding to an obsVar's property because you will have to remember to do that null check.

Unless you see some clear performance benefits from using visible in your situation, my recommendation would be to go with if because then you only have to write the check in one place and not multiple places.

Upvotes: 18

Beth Appel
Beth Appel

Reputation: 11

Try using $root.obsVar without the (). That should work for either if or visible. The difference between the two is that "visible" just hides the div, which will still exist in the DOM, but "if" leaves it out of the DOM.

Upvotes: 1

Related Questions