I’m working on replacing a legacy Webforms application with DotVVM. I’m trying to build a component for displaying various messages to the user. The contents should be initially hidden and only shown after a postback.
However, when I load the page, the container and some of its contents are temporarily visible before the Knockout applies styles to it and hides it.
I have tried using IncludeInPage as well as directly manipulating both the style and class attributes. They all work as needed after the postback. But nothing I have tried has prevented some of the contents from appearing on the page briefly before the Knockout runs and hides or removes it.
I do not know what else to try or what I am doing wrong.
For context, here is the content of the dotcontrol I am developing as it is now:
I think that if you wrap it inside a div with DataContext, it will solve the problem. If the DataContext is null when the page init, I don’t tink it will be rendered, so you will not have that loading styles bug.
I have DataContext on my control added to the master page. <ecx:MessageBox ID="MessageBox" DataContext="{value: MessageBox}" />
It is null until a click event on a link on the page creates a new instance of the MessageBoxViewModel.
I tried wrapping the ecx:MessageBox in a div and moving the DataContext to it but there was zero change in behavior.
My understanding of the way DotVVM works is if the DataContext is null, that element is not sent to the page. But instead it is sending all the control’s default HTML to the page and then the Knockout is hiding it later. i don’t like that behavior at all.
I’ve tried applying styles, css classes, direct manipulation. Nothing seems to prevent it from briefly showing it.
Ok, I finally figured it out. I have spent a lot of time reviewing DotVVM documentation, looking for examples, and trying everything I could think of.
As someone who is pretty new to DotVVM developing and needed more resources to overcome this issue, I’m posting the answer in hope of helping others.
The short answer is: use the built-in Visible property to hide content until you actually want it visible.
I actually had tried that but the ShowMessageBox property I was referencing was a member of the MessageBoxViewModel and not the page containing the MessageBox control. Since the MessageBox property (the DataContext in this case) was null, the value of ShowMessageBox was also null. Therefore the default Knockout behavior was occurring and the Visible property was not hiding as I needed it to.
Using the IncludeInPage property didn’t work because it only applies after the Knockout runs and then hides or shows the content.
What I needed to do was use the Visible property. The description for the Visible property is:
Gets or sets whether the control is visible. When set to false, style="display: none" will be added to this control.
I hope this is helpful and saves someone else from wasting many, many hours on something that seemed so trivial.
If the DataContext or IncludeInPage contains a value binding, DotVVM always has to send the HTML content, so it briefly shows up before the page initializes. You can duplicate the condition into the Visible property as you describe, or you can use Visible={value: _page.EvaluatingOnClient} to always hide the content coming from the server.
Thank you, @exyi. I tested it and it does behave the same as what I came up with. I did a search on the documentation site for _page.EvaluatingOnClient and EvaluatingOnClient. Neither one returns any results.