- Retrieve and display the user's details using `anvil.users.get_user()`.
- Link the Edit Details button to the SetDetailsComponent.
- Understand and resolve circular references in code imports.
- Refactor navigation code for better organization and maintenance.
Now that we have the AccountComponent layout completed we need to write the code that:
- Retrieves and displays the user's details
- Connects the Edit Details button to the SetDetailsComponent
We know that we can use anvil.users.get_user()
to retrieve user details and we also know that we can access these details like a dictionary.
We also have create the code to load the SetDetailsComponent, so we just need to copy that.
To display the current user's details:
- Open the AccountComponent in code mode
- We want to load the first and last name before the form opens, so go to the
__init__
method. - Add the highlighted code below
:linenos:
:lineno-start: 11
:emphasize-lines: 6 - 8
def __init__(self, **properties):
# Set Form properties and Data Bindings.
self.init_components(**properties)
# Any code you write here will run before the form opens.
user = anvil.users.get_user()
self.label_first_name.text = user["first_name"]
self.label_last_name.text = user["last_name"]
This should occur every time that the AccountComponent is loaded.
Let's test this first stage. Launch your website.
- Login if you have to
- Click on the Account link
- Check that the names have been populated
Now to link the Edit Details button.
To do this we will need to:
- Change into Layout mode to
- Create a handler for the button_edit_click event by clicking on click event
The link_register_click hander in the MainForm has the code to load the the SetDetailsComponent. Therefore:
- Open MainForm in code mode
- Go to the link_register_click event handler
- Copy the highlighted code below
:linenos:
:lineno-start: 68
:emphasize-lines: 3-6
def link_register_click(self, **event_args):
anvil.users.signup_with_form(allow_cancel=True)
self.content_panel.clear()
self.content_panel.add_component(SetDetailsComponent())
self.label_title.text = self.breadcrumb_stem + " - Details"
self.set_active_link("details")
- Return to AccountComponent
- Go to the the button_edit_click handler
- Paste the code
:linenos:
:lineno-start: 20
:emphasize-lines: 2-5
def button_edit_click(self, **event_args):
self.content_panel.clear()
self.content_panel.add_component(SetDetailsComponent())
self.label_title.text = self.breadcrumb_stem + " - Account - Details"
self.set_active_link("details")
Remember in the SetDetailsComponent, we used get_open_form
to reference the MainForm? We had to change all the self
references so they reference the MainForm.
We need to do that again.
First, add the highlighted code below.
:linenos:
:lineno-start: 20
:emphasize-lines: 2
def button_edit_click(self, **event_args):
main_form = get_open_form()
self.content_panel.clear()
self.content_panel.add_component(SetDetailsComponent())
self.label_title.text = self.breadcrumb_stem + " - Account - Details"
self.set_active_link("details")
Then, in the highlighted code, replace every self
with main_form
(hint: there are six of them.)
:linenos:
:lineno-start: 20
:emphasize-lines: 3-6
def button_edit_click(self, **event_args):
main_form = get_open_form()
main_form.content_panel.clear()
main_form.content_panel.add_component(SetDetailsComponent())
main_form.label_title.text = main_form.breadcrumb_stem + " - Account - Details"
main_form.set_active_link("details")
Notice that there is a brown squiggly line under SetDetailsComponent()
. This is telling you that the AccountComponent can't find the SetDetailsComponents. To fix this we need to use the code below to import SetDetailsComponents (remember, check the line numbers).
:linenos:
:lineno-start: 1
:emphasize-lines: 8
from ._anvil_designer import AccountComponentTemplate
from anvil import *
import anvil.server
import anvil.tables as tables
import anvil.tables.query as q
from anvil.tables import app_tables
import anvil.users
from ..SetDetailsComponent import SetDetailsComponent
Almost finished this, just the testing left to go.
Launch your website.
YIKES!
You will have gotten the following error:
What on earth is a circular reference?
Our circular refence is caused by our imports.
The SetDetailsComponent import statements are as below:
:linenos:
:lineno-start: 1
:emphasize-lines: 8
from ._anvil_designer import SetDetailsComponentTemplate
from anvil import *
import anvil.server
import anvil.tables as tables
import anvil.tables.query as q
from anvil.tables import app_tables
import anvil.users
from ..AccountComponent import AccountComponent
While our AccountComponent import statements are like this:
:linenos:
:lineno-start: 1
:emphasize-lines: 8
from ._anvil_designer import AccountComponentTemplate
from anvil import *
import anvil.server
import anvil.tables as tables
import anvil.tables.query as q
from anvil.tables import app_tables
import anvil.users
from ..SetDetailsComponent import SetDetailsComponent
If you look at the highlighted lines your will notice that:
- the AccountsComponent imports the SetDetailsComponent
- the SetDetailsComponent imports the AccountsComponent
So when you website launches and it reads all the code, the AccountsComponent wants to load all the code from the SetDetailsComponent which wants to load all the code from the AccountsComponent which wants to load all the code from the SetDetailsComponent which wants to load all the code from the AccountsComponent which wants to load all the code from the SetDetailsComponent which wants to load all the code from the... you get the idea.
Two items of code are referring to each other, hence the term circular reference.
This circular reference was caused because we have been very messy with out code, in particular our navigating code. You might have already noticed that we haven't been too stringent in applying the DRY principle, for example:
- we have navigation code in the MainForm, the SetDetailsComponent and the AccountComponent
- we also have repetition of similar code in each of the link click handlers in the MainCode
We need to refactor our code and bring all the navigation code into one place. This we will do in the next tutorial.
:class: note
Refactoring code means improving the structure and readability of your code without changing what it does. It's like cleaning up your room: you reorganize everything to make it easier to find and use, but you don't throw anything away or change how your room works.
By refactoring, you make your code clearer, easier to understand, and simpler to maintain, which helps you and others work with it more effectively in the future.