Reputation: 83818
Bearing in mind that similar questions have been answered here, I was wondering how one might go about having default text or HTML display inside a Knockout data-bind='foreach: list'
whenever the list is empty.
The solutions on the linked page don't quite seem to line up with this, and in any case I thought of another way to try to accomplish this with a custom binding like this:
text.default = {
update: function (element, valueAccessor) {
var $e = $(element),
obs = valueAccessor();
function _check_blank() {
// the element has content - so we do nothing
if ($e.text().trim()) {
return;
}
// the element is empty;
$e.text("Default Text")
}
// we use setTimeout to ensure that any other bindings complete
// their update
setTimeout(_check_blank, 0);
}
}
This seems to work reasonably well with simple observables but it does not work with the foreach
binding, though in any case I think the extender
suggestion in the above link is probably preferable for a few reasons -- the above code would have a number of caveats. Nevertheless, I threw this example in here because it somewhat highlights an alternative and food for thought.
All that being said, I would like to know what options there might be for providing a default in lieu of foreach
content.
One is to provide a wrapper in a simple if
, like this:
<!-- ko if: xyz().length -->
// foreach
<!-- /ko -->
<!-- ifnot: xyz().length -->
// default text
<!-- /ko -->
However this is not particularly elegant -- lots of code clutter.
Upvotes: 15
Views: 12315
Reputation: 1244
I know you have asked it long ago, but maybe today it can help someone; If you do it with an observable array or dependent observable (like filter results from a list), the above solution will not work.
You can use this method to force KO to go through this observable and see if it has changed using "with". Inside that loop, you should check $data length, if it's 0, there is no data to loop on ;)
<!--ko with: xyz -->
<div class="nodata" data-bind="visible:$data.length==0">
Sorry, no data
</div>
<!--/ko-->
Upvotes: 2
Reputation: 83818
The Knockout 3 extension Knockout Punches provides a default handler that can be used something like this:
<span data-bind="text: name | default:'Nobody'"></span>
More reading: KO Punches Documentation
Upvotes: 5
Reputation: 20802
Knockout gives you if
and ifnot
bindings. You just have to step back a bit from the element with foreach
; Its insides are just for each element, so when there are none, there aren't any insides.
<div data-bind="if: pets().length > 0">These are the pets:</div>
<div data-bind="if: pets().length == 0">There aren't any pets. To add a pet...</div>
<div data-bind="foreach: pets">
Editorial: Your question is important because empty lists are an opportunity to say something instead of showing a blank slate.
Upvotes: 32