Reputation: 1799
I am working on a single page applications that has a bunch of hidden divs, binded (or is it bound?) to KnockoutJS with visible:
. When page loads, they all momentarily flash on screen. I have tried moving my JS into the <head></head>
, but that had no effect, so loading JS at the bottom of the page is not what's causing it.
Unfortunately, visible:
binding does not propagate to CSS display
attribute, so I can not use display: none;
on page load, or visible:
will not work at all. Unless... I load the page with display: none;
and then change it the very first time I show the div to a user.
But is there a more elegant way to achieve this?
Upvotes: 25
Views: 6646
Reputation: 331
I ended up writing a custom binding to use instead of the default visible
.
function isHidden(el) {
var style;
style = window.getComputedStyle(el);
return (style.display === 'none')
}
ko.bindingHandlers['cssVisible'] = {
'update': function (element, valueAccessor) {
var value,
isCurrentlyVisible;
value = ko.utils.unwrapObservable(valueAccessor());
isCurrentlyVisible = !isHidden(element);
if (value && !isCurrentlyVisible) {
ko.utils.toggleDomNodeCssClass(element, 'ko-visible', true);
}
else if ((!value) && isCurrentlyVisible) {
ko.utils.toggleDomNodeCssClass(element, 'ko-visible', false);
}
}
}
Then some CSS to handle visibility
[data-bind*="cssVisible"]:not(.ko-visible) {
display: none;
}
Usage is the same as the visible
binding
<div data-bind="cssVisible: true"></div>
Upvotes: 0
Reputation: 108
I solved this by putting my "flashy" content in a script template and use ko's virtual elements to load the template when the variable is set by another virtual element.
For example:
<!-- ko if: myVariable -->
<!-- ko template: { name: 'myTemplate' } --><!-- /ko -->
<script type="text/html" id="myTemplate">
<ul data-bind="foreach: blah...">
<li></li>
</ul>
</script>
<!-- /ko -->
So when myVariable is set, the content of the script container will be put in place of the template virtual element. With this method you dont see any flashing content :-)
Upvotes: 5
Reputation: 5412
Wth KnockoutJS, I work around this problem by defining a CSS class called hidden
with display:none
, then I'll add this class and binding to the flashing container:
class="hidden" data-bind="css: { hidden: false }"
Upvotes: 57