I have an issue where knockout.js 2.0 isn't showing my item when a CSS style is applied to it. It won't update the display with the style applied to it. If it is off it works.
CSS
.success { display:none }
HTML
<div data-bind="visible: site.signUp.success()" class="success">
Thanks for signining up. You will recieve an email from us in the near future.
</div>
JS
app.viewModel.site.signUp.success(true);
I have an issue where knockout.js 2.0 isn't showing my item when a CSS style is applied to it. It won't update the display with the style applied to it. If it is off it works.
CSS
.success { display:none }
HTML
<div data-bind="visible: site.signUp.success()" class="success">
Thanks for signining up. You will recieve an email from us in the near future.
</div>
JS
app.viewModel.site.signUp.success(true);
Share
Improve this question
edited Jan 11, 2012 at 1:49
Mike Flynn
asked Jan 10, 2012 at 3:00
Mike FlynnMike Flynn
24.3k59 gold badges195 silver badges367 bronze badges
1
- I almost feel like this is a bug, thought the documentation does say that CSS display styles still work in conjunction with the visible binding. The main issue I have is I find it hacky to have to write the CSS binder and defeats a lot of the usefulness of the visible binding because I get flickering elements in my page without the CSS binding. – Lo-Tan Commented May 14, 2012 at 14:48
5 Answers
Reset to default 6In the period of time before Knockout.js applies bindings, you can prevent the initial rendering/flashing effect by setting the default display style to none
.
<div style="display: none" data-bind="visible: site.signUp.success">
Thanks for signining up. You will recieve an email from us in the near future.
</div>
I created a fiddle that shows how you can use the css binding in Knockout to do this. http://jsfiddle/johnpapa/vwcfT/
Here is the HTML:
Success Flag: <input type="checkbox" data-bind="checked:site.signUp.success"></input>
<div data-bind="visible: site.signUp.success" >
Thanks for signining up. You will recieve an email from us in the near future.
</div>
<br/><br/>
<span data-bind="text:site.signUp.success"></span>
<div data-bind="css: { success: site.signUp.success}" >
Thanks for signining up. You will recieve an email from us in the near future.
</div>
The first DIV in the example just uses the visible binding, since you dont really need a css class to do this. The second DIV in the example binds to a css class named "success" if the site.signUp.success observable is true. This is more verbose than the first, but could be useful if you needed your css class to do more than just set visibility.
Hope this helps.
Here is the javascript:
var viewModel = {
site: {
signUp: {
success: ko.observable(true)
}
}
};
ko.applyBindings(viewModel);
That's because the success style is defined as display:none
, which is equivalent to visible = false
. Your CSS class is cancelling out your site.signUp.success()
call.
If you want your DIV to show up only when site.signUp.success() == true
, just do this:
<div data-bind="visible: site.signUp.success">
Thanks for signining up. You will recieve an email from us in the near future.
</div>
It might be a bit late but I found the following useful. Instead of fixing every element with a visibility control, just wrap a div around all your pre-hidden elements as follow:
<div style="display:none" data-bind="visible: true">
Some pre-hidden elements
<div data-bind="visible: myVisibleFoo">...</div>
<div data-bind="visible: myVisibleBar">...</div>
Other pre-hidden elements
...
</div>
The whole section of elements is hidden initially and is only shown after KO has applied bindings. I usually wrap the whole page with it to avoid any flashing problem.
Just run into this myself; I can see why the did it this way, but it is handy to set a default visibility of none on late loaded elements on the page so they don't flash as scripts are loaded. The nicest way I could find of doing this was just to create a simple custom binding:
ko.bindingHandlers.forceVisible = {
update:
function(el, f_valueaccessor, allbindings, viewmodel, bindingcontext)
{
if(ko.unwrap(f_valueaccessor()))
el.style.display = 'inherit';
else
el.style.display = 'none';
}
};
You have to be a little bit careful when setting up your styles; if you are using a div
and your CSS sets it to display:inline-block
then this code will not work - it will have block display when the inherit
is applied. This simple solution was fine for my use case, however.