Navigation
An Anvil app is composed of Forms, and navigation is simply a matter of displaying the correct Form.
Displaying a new page
To display a new page, call open_form()
(from the anvil
module), and pass in the instance of the Form that you’d like to display as your new page.
When you do this, the new Form takes over entirely and becomes the top-level Form. The old Form is no longer visible.
If you pass any extra parameters into open_form()
, they are passed to the new Form’s constructor:
class Form1(Form1Template):
# ...
def btn1_click(self, **event_args):
open_form('Form2', my_parameter="an_argument")
As well as specifying a Form by name, you can also create an instance of the Form yourself and pass it in. This code snippet is equivalent to the previous one:
from ..Form2 import Form2
class Form1(Form1Template):
# ...
def btn1_click(self, **event_args):
frm = Form2(my_parameter="an_argument")
open_form(frm)
Note that Forms are not available to other Forms unless you explicitly import them.
Each Form has its own module, which has the same name as the Form, so to import Form2 from inside Form1, you use from ..Form2 import Form2
.
Resetting the current Form
To reset the Form that’s currently open, just run open_form(form_name)
. For example, if Form1 is open, run open_form("Form1")
.
Replacing just the main content
Oftentimes, you’ll want to build an app that has a navigation bar so that users can switch to different pages in your app. The best way to build this is by
creating a Layout Form that has a Slot for the main content and a navigation bar with Links inside. You can then add Forms to your app that use the Layout Form as their Layout. The Links in the Layout Form should each have an event handler that calls open_form
to switch to the desired Form.
def about_us_link_click(self, **event_args):
"""This method is called when the link is clicked"""
open_form('AboutUs')
Because the Forms are all using the same layout, the pages in your app will have the same navigation bar.
Check out our tutorial on creating a multi-page app to see a worked example of using a Layout Form to navigate between pages:
Advanced tip: using one click handler for all Links
You don’t have to write one click handler per Link. You can get which Link has been clicked from the
event_args['sender']
, so you can use that to work out which Form to instantiate.
Say, for example, your app has a Layout that contains three navigation links called home_link
, about_link
, and contact_link
, as well as three additional Forms called ‘Home’, ‘About’ and ‘Contact’. You can set each Link’s tag
attribute to the name of the Form you want to open (or an instance of that Form):
from .Home import Home
from .About import About
from .Contact import Contact
class Form1(Form1Template):
def __init__(self, **properties):
# Set Form properties and Data Bindings.
self.init_components(**properties)
# set each Link's `tag.form_to_open` attribute to an instance of the Form you want to open
self.home_link.tag.form_to_open = Home()
self.about_link.tag.form_to_open = About()
self.contact_link.tag.form_to_open = Contact()
Then, you can configure one click handler to use for home_link
, about_link
, and contact_link
in your top-level Form:
def nav_link_click(self, **event_args):
"""A generalised click handler that you can bind to any nav link."""
# Find out which Form this Link wants to open
open_form(event_args['sender'].tag.form_to_open)
You can then set the nav_link_click
function as the ‘click’ event handler for home_link
, contact_link
and about_link
:
Using the URL hash
get_url_hash()
gets the decoded hash (the part after the ‘#’ character) of the URL used to open this app.
self.label_1.text = f"Our URL hash is: {get_url_hash()}"
You can create a URL-based navigation system by opening a particular Form depending on the URL hash:
if get_url_hash() == 'stats':
from Stats import Stats
self.content_panel.clear()
self.content_panel.add_component(Stats())
elif get_url_hash() == 'analysis':
from Analysis import Analysis
self.content_panel.clear()
self.content_panel.add_component(Analysis())
Query params
If the first character of the hash is a question mark (e.g. https://myapp.anvil.app/#?a=foo&b=bar
) or an exclamation point followed by a question mark (e.g. https://myapp.anvil.app/#!?a=foo&b=bar
), it will be interpreted as query-string-type parameters and returned as a dictionary (e.g. {'a': 'foo', 'b': 'bar'}
).
get_url_hash()
is available in Form code only.
Do you still have questions?
Our Community Forum is full of helpful information and Anvil experts.