xlecoustillier
xlecoustillier

Reputation: 16351

Knockout conditional binding (but not the native "if" way)

I have a case that look like this (excessively simplified):

<!-- ko if: readOnly() -->
<a href="url" data-bind="click: ToggleReadOnly()" />
<!-- /ko -->
<!-- ko ifnot: readOnly() -->
<a href="url" data-bind="visible: someObservable" />
<!-- /ko -->

Because of multiple other things around that would multiply the tests and duplicate a lot of code, I'd need to be able to do this in one line, something like:

<a href="url" data-bind="if: readOnly() { click: ToggleReadOnly() } else: { visible: someObservable }"  />

Is there a way to do that ?

Upvotes: 0

Views: 181

Answers (1)

Jeff Mercado
Jeff Mercado

Reputation: 134801

There are a couple of approaches you could take to this. Each with it's own strengths and weaknesses. but I will focus on using templates.

Create a template for each state where it is rendered in readonly mode or not. You'll only need to add to your model a function that decides which template to use.

<script type="text/html" id="template-readonly-link">
    <a href="#" data-bind="click: ToggleReadOnly">ReadOnly</a>
</script>

<script type="text/html" id="template-readwrite-link">
    <a href="#" data-bind="visible: someObservable">ReadWrite</a>
</script>

<!-- ko template: { name: selectTemplate } --><!-- /ko -->
function ViewModel() {
    this.readOnly = ko.observable(true);
    this.someObservable = ko.observable(true);

    this.ToggleReadOnly = function (data, event) {
        this.readOnly(!this.readOnly());
        return false;
    }.bind(this);
    this.selectTemplate = function (data) {
        return this.readOnly()
            ? 'template-readonly-link'
            : 'template-readwrite-link';
    }.bind(this);
}

fiddle

You can explore other approaches such as custom components, custom bindings, etc. But this may be the easiest to implement.

Upvotes: 1

Related Questions