SOME CONTEXT:
My app has 2 forms:
- Form 1 (startup form, having no content)
- Form 2 (has static content)
WHAT I WANT:
I want the app to start with Form1 and automatically navigate from there to Form2. Pretty simple, I know.
WHAT I DID (MY CODE):
Form 1 code:
from ._anvil_designer import Form1Template
from anvil import *
import anvil.server
import anvil.google.auth, anvil.google.drive
from anvil.google.drive import app_files
import anvil.users
import anvil.tables as tables
import anvil.tables.query as q
from anvil.tables import app_tables
from ..Form2 import Form2
class Form1(Form1Template):
def __init__(self, **properties):
self.init_components(**properties)
form=Form2()
open_form(form)
Form 2 code:
from ._anvil_designer import Form2Template
from anvil import *
import anvil.server
class Form2(Form2Template):
def __init__(self, **properties):
# Set Form properties and Data Bindings.
self.init_components(**properties)
print("components loaded") # This gets printed.
AN INTERESTING POINT:
Interestingly, “components loaded” gets printed in Form2 in the output console but the static content does not appear!
FOR REFERENCE:
Here’s the link to clone the application:
https://anvil.works/build#clone:Z6P2Y525JOUD2HCO=4D52QCWZJSIJX3VBNTQ2LCHK
What is it that I’m doing wrong? This is such a simple scenario.
Seeking some Anvil community expertise.
The problem is that you used an instance of Form2 as the argument in open_form. However, open_form takes a string argument, so you would do
open_form('Form2')
Does not work!
I initially tried this itself (why would I go with a complex way?) and it did not work. That’s why I tried passing instance of Form2 as an argument to open_form instead, and this does not work either.
FYI you can pass Form objects to open_form
too. But the problem here is something else. You are running this code on init when the first form hasn’t even opened. This is why the code is not working.
You can pass this code to form_show
event.
Also, I think it will be much better if you set a startup module instead of startup form.
3 Likes
Below is the code generated when a form is created:
from ._anvil_designer import Form3Template
from anvil import *
import anvil.server
class Form3(Form3Template):
def __init__(self, **properties):
# Set Form properties and Data Bindings.
self.init_components(**properties)
# Any code you write here will run when the form opens.
The last line (comment) clearly says “Any code you write here will run when the form opens.”
Secondly, what you’re suggesting can be at best called a practice (subjective to individual’s design choice). It still does not technically explain (given the code that exists) the unexpected behavior.
I tried form show event as you suggested and it works perfectly. Thanks man!
(though still confused why what I did didn’t work as it was totally as per the anvil official docs for navigating between forms)
Not sure about the reason for the comment but this behavior has been discussed multiple times on the forum. Just like with any other Python class, any code you add in __init__
is run while creating a new form object. So basically, when you call the open_form
method, it will first create the form object and then open it. Here’s the breakdown of the process here
- Anvil creates Form 1 object by calling its
__init__
method
- During the
__init__
method, your code opens form 2
- Now that Anvil has called the
__init__
method for form1, it wents on to open it. So even though Form 2 was opened, it gets replaced by form 1 again
You see what’s happening now?
And if you want to, you can also conduct a small experiment in which you call any kind of error after opening form 2. Like in this case, make your code
class Form1(Form1Template):
def __init__(self, **properties):
self.init_components(**properties)
form=Form2()
open_form(form)
0/0 #Or any other way to crash your app
You will see that your app gets stuck at form 2 now due to a failure to create form 1 object. You could also add a sleep to see that form 2 will load and then be replaced by form 1.
Edit I don’t think there is any example in Anvil Docs which calls the form during the __init__
method.
2 Likes
Thanks for the clarification. It was quite helpful.
However, I’d further want to understand how init works in the context of anvil’s overall design. Could you also provide some part of anvil docs that I can go through to have a deeper grasp of how and in what sequence things happen here?
I don’t think the docs go any further than this. But just remember that forms are treated like python classes. So the __init__
method here just works as it would for any python object. So once you are familiar with the concept of init in python, you can easily apply it to Anvil. And there are some great resources online for it (I don’t have any specific one in mind).
And if you still have doubts, ask that specific question on the forum.
1 Like