JSFiddle - React, Tailwind, and code Playground
HTML
<h3>X is
<u data-bind='if: x'>True</u>
<u data-bind='ifnot: x'>False</u>
<button data-bind='click: function () { x(!x()) }'>Toggle</button>
</h3>
<h1>Element - Element</h1>
<div data-bind='if: x'>IF X</div>
<div data-bind='else'>ELSE</div>
<h1>Element - Comment</h1>
<div data-bind='if: x'>IF X</div>
<!-- ko else -->ELSE
<!-- /ko -->
<h1>[ifnot] Element - Element</h1>
<div data-bind='ifnot: x'>NOT X</div>
<div data-bind='else'>ELSE (X)</div>
<h1>Comment - Element</h1>
<!-- ko if: x -->IF X
<!-- /ko -->
<div data-bind='else'>ELSE
</div>
<h1>Comment - Comment</h1>
<!-- ko if: x -->IF X
<!-- /ko -->
<!-- ko else: -->ELSE
<!-- /ko -->
<h1> Comments (nested) - Comment</h1>
<!-- ko if: x -->
IF X (<!-- ko text: "" + x() --><!-- /ko -->)
<!-- /ko -->
<!-- ko else -->
ELSE
<!-- /ko -->
<h1> Foreach (empty) - Else</h1>
<!-- ko foreach: [] -->
Don't see me!
<!-- /ko -->
<!-- ko else -->
List is empty
<!-- /ko -->
<h1> Foreach ([1,2,3]) - Else</h1>
<!-- ko foreach: [1,2,3] -->
<em data-bind='text: $data'></em>
<!-- /ko -->
<!-- ko else -->
Don't see me!
<!-- /ko -->
<h1> Foreach (ko.obs(undefined)) - Else</h1>
<!-- ko foreach: ko.observable(undefined) -->
Undefined.
<!-- /ko -->
<!-- ko else -->
List is empty
<!-- /ko -->
CSS
body {
padding: 8px 2em;
}
h1 {
font-size: 1em;
border-bottom: 1px solid #AAA;
}
JavaScript
/*
For a plugin based upon this fiddle:
https://github.com/brianmhunt/knockout-else
*/
// Re. https://github.com/knockout/knockout/issues/962
// See knockout virtualElements
function startsCommentBinding(node) {
return (node.textContent || node.innerText)
.match(/^(<!--)?\s*ko\s+[\s\S]+/);
}
function endsCommentBinding(node) {
return (node.textContent || node.innerText)
.match(/^(<!--)?\s*\/ko/);
}
function getBindingConditional(node, bindingContext) {
var conditional;
var bindings = ko.bindingProvider.instance.getBindings(node, bindingContext);
if (!bindings) {
return
} else if (conditional = bindings['if']) {
return ko.pureComputed(function () {
return !ko.unwrap(conditional)
});
} else if (conditional = bindings['ifnot']) {
return ko.pureComputed(function () {
return ko.unwrap(conditional)
});
} else if (conditional = bindings['foreach']) {
return ko.pureComputed(function () {
var conResult = ko.unwrap(conditional);
return !conResult || conResult.length === 0;
});
}
return
}
function prevVirtualNode(node) {
var depth = 0;
do {
if (node.nodeType === 8) {
if (startsCommentBinding(node)) {
if (--depth == 0) {
return node;
}
} else if (endsCommentBinding(node)) {
depth++;
}
}
} while (node = node.previousSibling);
return;
}
function getPrecedingConditional(element, bindingContext) {
var prevSib = element;
do {
prevSib = prevSib.previousSibling;
} while (prevSib && [1, 8].indexOf(prevSib.nodeType) === -1);
if (!prevSib) {
throw new Error("Unmatched conditionals!");
return;
}
if (prevSib.nodeType == 1) {
return getBindingConditional(prevSib, bindingContext);
} else if (prevSib.nodeType == 8) {
...