Challenges with the "visible" binding

2,936 views
Skip to first unread message

Justin

unread,
Jun 23, 2011, 6:41:34 PM6/23/11
to KnockoutJS
It appears that the only way to start out with a DOM element being
hidden prior to Knockout.js running its logic via the "visible" data-
bind command is to have an inline style attribute defined on the
element to set the display:none. Setting the display:none value via
CSS either by a class reference or an element id (#) results in the
element never being visible even when the KO logic results in a valid
visible value. From the docs, it sounds like this is due to KO
applying the CSS rules after it has handled changing the
element.style.display value.

The drawback with the way this currently works is that the browser
will render that DOM element prior to KO doing that logic check, so
the user experience is a "flash" of the potential visible content even
if the KO expression evaluates to hidden. Of course, it can be handled
by adding the inline styling in the element, but it would be ideal to
keep that out of the markup.

Is there any way around this in the current KO code? If not, is it
something that could be added to a future version? Maybe an option to
toggle when it does the element.style.display change (before or after
CSS application).

By the way, thanks for crafting Knockout.js and making it available.
It is an extremely valuable library. Much appreciated!

Mark Bradley

unread,
Jun 23, 2011, 8:13:25 PM6/23/11
to knock...@googlegroups.com
I tend to handle this situation using CSS.

given some html with a data binding like this:

<div id="wrapper" data-bind="css: { editing: fieldForEditingProp }">
<div id="edit">
<!-- stuff -->
</div>
<div id="show">
<!-- stuff -->
</div>
</div>

then I have styles:

#wrapper.editing #edit, #wrapper #show {
// show "edit" and hide "show" when "editing"
display: auto;
}
#wrapper.editing #edit, #wrapper #show {
// show "show" and hide "edit" when "editing"
display: show;
}

This technique effectively moves the show/hide implementation to CSS,
but also has it depend on the viewModel so you can control it easily.

--
-barkmadley
sent from an internet enabled device

Mark Bradley

unread,
Jun 23, 2011, 8:14:52 PM6/23/11
to knock...@googlegroups.com
On Fri, Jun 24, 2011 at 10:13 AM, Mark Bradley <barkm...@gmail.com> wrote:
> I tend to handle this situation using CSS.
>
> given some html with a data binding like this:
>
> <div id="wrapper" data-bind="css: { editing: fieldForEditingProp }">
>  <div id="edit">
>    <!-- stuff -->
>  </div>
>  <div id="show">
>    <!-- stuff -->
>  </div>
> </div>
>
> then I have styles:
>
> #wrapper.editing #edit, #wrapper #show {
>  display: auto;
> }
> #wrapper.editing #edit, #wrapper #show {
>  display: none;
> }

got the right property value this time and removed comments because
they were confusing.

rpn

unread,
Jun 23, 2011, 10:10:24 PM6/23/11
to knock...@googlegroups.com
I agree with Mark, the css binding works well for this situation.  It will add or remove a css class based on the truthiness of the value that you pass to it.

For example, you can set up a css class named "hideMe", start your elements with this class on it, and use the css binding to determine whether it should stay hidden or be shown.

<div data-bind="css: { hideMe: yourObservable }"></div>

or

<div data-bind="css: { hideMe: !yourObservable() {"></div> 

depending on whether or not the observable indicates that it should be visibile or not, as the logic will now be opposite of what you were passing to the visible binding.

Justin

unread,
Jun 23, 2011, 10:18:21 PM6/23/11
to KnockoutJS
Thanks! I plan on switching over to this approach. Works like a charm
to start with the element hidden and then test the opposite of the
observable value that reports if the element should be visible to
remove the class that does the hiding.

<div class="Hidden" data-bind="css: { Hidden : !
fieldToReportIsVisible() }">This is visible</div>

with a style

.Hidden { display:none; }


I totally missed the css binding docs (was a late night)...thanks for
pointing that out!

- Justin


On Jun 23, 7:10 pm, rpn <rnieme...@gmail.com> wrote:
> I agree with Mark, the css<http://knockoutjs.com/documentation/css-binding.html> binding

Pradeep Hegde

unread,
Feb 8, 2013, 6:39:56 AM2/8/13
to knock...@googlegroups.com, schw...@gmail.com
Hi ,

Thanks for this information, i am able to hide/ show the elements using css but still the user experience is a "flash" of the hide element. I am not sure where i am doing wrong.
My CSS class is > ShowHide {display:none} and in my .cshtml >  data-bind="css: {ShowHide: !RegisterVisible()}"

Can you please guide me in the right direction

Nikhilchandra Rathod

unread,
Feb 8, 2013, 7:45:12 AM2/8/13
to knock...@googlegroups.com, schw...@gmail.com
Hi,

Check the below link for both bindings "Visible" and "class"



Thanks

b...@mca.mk

unread,
Feb 24, 2014, 4:19:15 AM2/24/14
to knock...@googlegroups.com, schw...@gmail.com
The scenario is the following (i reused all your code):

// Add your javascript here

var ViewModel = function(){
  
  var self = this;
  self.RegisterVisible = ko.observable(false); // -> NOTE 1: if you start with false value
  self.showhide = function(){
    self.RegisterVisible(!self.RegisterVisible());
  };
};

$(function(){
  // -> NOTE 2: imagine viewmodel init took 5 seconds
  setTimeout(function() {ko.applyBindings(new ViewModel())}, 5000);
});

You can clearly see that the two elements are visible for 5 seconds, then the viewmodel is initialized and they are hidden. Now i know 5 seconds is highly unlikelly scenario but with 500 milliseconds to 1 second you get the "flash" user expirience
Reply all
Reply to author
Forward
0 new messages