Page.Open Event - When should and shouldn't it be used??

Hello all.

I came across a post the other day, which of course I cannot find again, that says that the webpage.open event really should not be used, since it is really not 'open" but rather “pre-open”. Instead the “shown” event should be used.

My question is, when and for what purposes should the webpage.open and webpage.shown events be best used, and when should either or both be stayed away from?

I ask the question for a few reason, not the least of which is proper coding. The other big one is how, when and where should objects created be destroyed so that there are no memory leaks and sessions close (and stay closed) properly.

Thanks in advance for your help all!
Tim

I think the issue is that in the Open event, not all the controls have initialised themselves, so calling on values in them may produce errors. The Open event behaves itself better than it used to! I use both Open and Shown.
The problem with Shown is that it runs EVERY time the WebPage or container is brought to the foreground, not just the first time.

[quote=351154:@David Cox]I think the issue is that in the Open event, not all the controls have initialised themselves, so calling on values in them may produce errors. The Open event behaves itself better than it used to! I use both Open and Shown.
The problem with Shown is that it runs EVERY time the WebPage or container is brought to the foreground, not just the first time.[/quote]

unless you have an indicator that get set on open and use in the on shown to only do certain if first time.

Yes, you are right. I was going to mention that sometimes I have a Boolean (default = False) called FirstRun, then only run the Shown methods when FirstRun = false, then set it as True when Shown has finished running.

The only issue is that the WebPage has already drawn once by this stage (buttons ready to be clicked) and we are changing it to what we want, so I lock everything down first, then unlock them in the Shown event by calling an UpdateButtons method.

It’s a little hard to tell what is and is not available in the open event. In my experience you can pretty much preset any values or properties you want to display that are things that would be displayed when the control is initially shown. For example the text of a web label is fine to set in the Open event. The initial style is fine to set in the open event, even the location on the window is fine to change. You cannot do things that act on a control already visible like adding rows to a listbox or setting the URL of a webHTML control.

If you wait till the shown event the control will first appear in whatever your default design time state was, which might be fine. Then a moment later the interface will change as the shown event fires and your new values get sent. This drives me crazy in an otherwise good user interface so I use the open event to preset the interface whenever possible. The Shown event requires a back and forth to the server too, the more things you have on a page that need a shown event the slower this will become, especially if you’re communicating to a mobile device or over an SSL connection. It can be quite some seconds after the interface initially appears before it is ready to actually accept any user input. This can also be very frustrating.

The Open() event represents when the control was instantiated on the server. As the controls are instantiated on the server javascript is created and sent to the client (technically javascript is retrieved by the client in polling operations).

So there is a window of time however insignificant that the Xojo Web control exists so far as the server is concerned but the browser has not yet received or rendered that control. When you perform an operation on said control like changing the Text property there could be a circumstance where the client is trying to update the Text property of a control before the control was actually instantiated in the client.

While you would think this would be impossible because the javascript to instantiate the control would exist before the property change you have to remember that TCP does not specifically protect the order of data only that it all gets there. So there are circumstances where using the Open() event is ill advised. Some examples include:

  • Slow or latent network conditions
  • Slow web browser
  • Slow javascript rendering in otherwise fast browser

The problem lies in the fact that those attributes are not known to the server at that stage (if ever). However as someone else indicated if you use Shown() exclusively you will likely find controls in a default incorrect state. The fix here is simple:

  • Mark controls visibility to false
  • Display a loading mechanism of some kind. Fast browsers and fast network conditions will often never see this.
  • On the Shown() events make the necessary changes to your controls and mark them as visible.

The reality is there is very little programmatic distinction between Open() and Shown(). What I mean by that is there is almost never a situation where code should be in Open() and would not work just as well in Shown(). Even if there was you could simply override the control Constructor() to gain similar timing (control being instantiated on server before client) as today’s Open() event.

Therefore it is my conclusion that Xojo Web should not use the Open() event as it currently does. Open() should be changed to represent client instantiation. Shown() should represent every time the control is made visible after some period of not being visible (page/container changes, etc).

[quote=351250:@James Sentman]It’s a little hard to tell what is and is not available in the open event. In my experience you can pretty much preset any values or properties you want to display that are things that would be displayed when the control is initially shown. For example the text of a web label is fine to set in the Open event. The initial style is fine to set in the open event, even the location on the window is fine to change. You cannot do things that act on a control already visible like adding rows to a listbox or setting the URL of a webHTML control.

If you wait till the shown event the control will first appear in whatever your default design time state was, which might be fine. Then a moment later the interface will change as the shown event fires and your new values get sent. This drives me crazy in an otherwise good user interface so I use the open event to preset the interface whenever possible. The Shown event requires a back and forth to the server too, the more things you have on a page that need a shown event the slower this will become, especially if you’re communicating to a mobile device or over an SSL connection. It can be quite some seconds after the interface initially appears before it is ready to actually accept any user input. This can also be very frustrating.[/quote]

Open() is quite literally a parallel to the Constructor() event and likely called in it. See: http://documentation.xojo.com/index.php/WebControl.Open

Shown() is not so much a back/forth with the server as acknowledgement to the server that the control was rendered. This event will be processed by both client and server regardless if whether you have exercised usage of the event or not in your code.

I had this issue where the users login into a WebApp had different privileges e.g. whether they could access the Admin and Finance areas via the Toolbar. If set in the Shown event, the toolbar would show the ‘Admin’ and ‘Finance’ icons then immediately these icons would disappear (when I deleted them in Shown event).

I fixed this my making the whole toolbar invisible in the IDE, then removing the unwanted items and making the toolbar visible, all in Shown. Now the low-privileged user never sees the icons they are barred from when logging in.

I think Xojo’s decision to call that event “open” is a bit misleading, as we are lured into thinking it might mean the same thing it does in a desktop project - which apparently it does not. Thanks to Phillip for shedding some light on the issue (and for Tim for doing the dirty job of asking the question I was too embarrassed to ask ;-)).

[quote=351262:@Phillip Zedalis]Open() is quite literally a parallel to the Constructor() event and likely called in it. See: http://documentation.xojo.com/index.php/WebControl.Open

Shown() is not so much a back/forth with the server as acknowledgement to the server that the control was rendered. This event will be processed by both client and server regardless if whether you have exercised usage of the event or not in your code.[/quote]

The open event is when the control is being setup on the server but no code has been sent to the browser. In most cases any property that you could set at design time in the IDE is available to be altered in the controls Open event. Other things, such as I mentioned above, cannot be done to a control as they are not something that is sent along with the control during it’s initial setup. The control is queued up for sending to the browser AFTER the open event. Any changes you make to any IDE available properties in the open event will go in the initial load of the control. You do not have to wait for shown to change the text of a web label for instance.

You can absolutely verify that this is OK or not ok by watching the networking timeline in any of the browser developer tools. You’ll see the initial load of the control, and then you’ll see it making XHRs for things like shown events. If you see your control appear only once in the upload with the proper settings already there then your value was present when the javascript and HTML was created and queued up for the transmission to the browser after the open event. If you see the control sent with it’s default properties and you see a javascript snippet later changing the value then indeed, the control and your changes to it were sent separately and it is possible you might hit a problem where your change arrived before the control it was destined for.

Xojo will open several keep-alive connections from the browser for events and loading and so the timing of when what gets setup and ready is non-determinant as if all the javascript and html went down a single pipe. So that is true. But I’ve verified for the things I do that changing the IDE default properties in the controls Open event cannot lead to the random javascript errors that could if you were changing things later. There ARE some properties or things as we’ve already discussed that do not change default properties and that you can’t do until the control is actually at the browser, things like executeJavascript or setting the URL for a webHTML control.

Shown() is SOMETIMES a back and forth with the server, and not other times :wink: I don’t fully understand what does what yet. It seems that some controls can get their shown event just after their javascript has entered the pipe, or perhaps it’s forwarded down from the page shown event to the controls. Other controls like embedded container controls seem to get a shown event that is a separate XHR for each one. But not always. I don’t know why or what yet but it’s entirely possible to build a dynamic page that makes dozens of separate XHRs each one destined for a shown event. You can see these in the same networking timeline on the browser.

[quote=351261:@Phillip Zedalis]While you would think this would be impossible because the javascript to instantiate the control would exist before the property change you have to remember that TCP does not specifically protect the order of data only that it all gets there. So there are circumstances where using the Open() event is ill advised. Some examples include:

Slow or latent network conditions
Slow web browser
Slow javascript rendering in otherwise fast browser[/quote]

It’s not TCP that is the problem. It definitely keeps your packets in order or horrible things would happen :wink: The problem is that the browser opens several keep-alive connections back to the server to load everything so there is no way to tell for sure when which part will finish loading before any other part.

I don’t know why TCP I meant API as in the Xojo javascript API. I think I am getting older and was thinking about another post.

Of course underneath TCP network data can arrive out of order but TCP orders it correctly via ACK acknowledgement behind the scenes.

James you wrote a lot but I can explain further why you should not use Open() and should use Shown().

Let’s take a look at what is likely happening behind the scenes:

WebLabel

  • Constructor() - Start = Do any Xojo framework initialization.
  • Open() = You change the .Text property of the label
  • Constructor() - End = Send the javascript to the client to initialize the label in the browser.

So in this case in your example of changing a .Text property you are correct that Open() can be used. Why? Because the .Text property is simply a property and does not impact program execution flow. The default .Text property from the IDE simply gets changed prior to the javascript being initialized in the browser.

Now let’s look at a more complex example:

WebListBox

  • Constructor() - Start = Do any Xojo framework initialization.
  • Open() - Start = You call WebListBox.AddRow() to add a row.
  • AddRow() = Creates the javascript to add the row to the listbox and sends to client.
  • Open() - End = The Open() event finishes
  • Constructor() - End = Send the javascript to the client to initialize the listbox in the browser.

Now you can clearly see the problem. To the server all is well. The WebListBox was initialized and you added a row. However to the client browser this will fail and give you a nasty pop up javascript exception. Why? The javascript code to add the row was executed prior to the code to actually create the listbox in the first place.

Solution: Do your control manipulation in Shown()

Also keep in mind you will likely NOT see this behavior when in development mode. There is zero network latency and only one user using your app. My previous example is not technically true because the code is sent to the browser likely at the beginning of the Open() event. However for all practical purposes you should consider the simplified example above.

In the real world with network latency and more specifically Xojo’s event model I think what happens is when you call AddRow() you give Xojo an opportunity to context switch. Somehow with Xojo’s internal timers or event model in a latent environment (and possibly with many users) the order of operations ends up wrong and you see the error I wrote above. It is easily demonstrable on a live server and browser environment with even minimal network latency and users.

So while Open() in theory should be safe it is often not. There are many many posts on these forums where the Xojo engineers have indicated you should not use Open() to manipulate the control. Also the documentation specifies that Open() occurs prior to browser initialization. So if you do manipulate controls like the AddRow() example then you are putting faith in Xojo to construct the messages in the correct order and in my experience and experience of others it fails to do this in production.