SetDetailsComponent Navigation

In last tutorial’s test you would notice that once you have saved the details, the SetDetailsComponent remained loaded. What we want to do is load the AccountComponent so the user can see the current value of their first name and last name.

Admittedly, at the moment, the AccountComponent only has a title, but we’ll fix that in the next tutorial.

Plan

The idea is pretty simple, we will need to add the step of loading the AccountComponent and change the lable_title_text to the end of the button_save_click handler. We can copy the appropriate code from link_account_click handler in the MainForm.

Code

Copying the code

First we will copy the text we need.

  1. Open the MainForm in code mode and find the link_account_click handler.

  2. Copy the highlighted code

63  def link_account_click(self, **event_args):
64    """This method is called when the link is clicked"""
65    self.content_panel.clear()
66    self.content_panel.add_component(AccountComponent())
67    self.label_title.text = self.breadcrumb_stem + " - Account"
68    self.set_active_link(("account"))

Now we need to paste it into the button_save_click handler.

  1. Open SetDetailsComponent in code mode and find the button_save_click handler

  2. Paste the code to the bottom of the handler, as below

17  def button_save_click(self, **event_args):
18    
19    if self.text_box_first_name.text == "":
20      self.label_error.text = "First name cannot be blank"
21      self.label_error.visible = True
22      return
23
24    if self.text_box_last_name.text == "":
25      self.label_error.text = "Last name cannot be blank"
26      self.label_error.visible = True
27      return
28
29    self.label_error.visible = False
30    anvil.server.call("update_user", 
31                      self.text_box_first_name.text, 
32                      self.text_box_last_name.text)
33
34    self.content_panel.clear()
35    self.content_panel.add_component(AccountComponent())
36    self.label_title.text = self.breadcrumb_stem + " - Account"
37    self.set_active_link(("account"))

Testing

Now launch your website for testing:

  1. Register another user (you might have to logout first).

  2. Enter their first name and last name

  3. Click Save Details

  4. WHAT JUST HAPPENED?

You would have just got the following runtime error:

content panel error

Types of Programming Errors

Programming errors fall into three categories

  1. Syntax Errors

    • Occur when the code doesn’t follow the rules of the programming language.

    • Detected by the compiler or interpreter before running the code.

    • Example: Missing a closing parenthesis.

  2. Runtime Errors

    • Occur during the execution of the program.

    • Cause the program to crash or produce unexpected results.

    • Example: Dividing by zero.

  3. Logic Errors

    • Occur when the code runs but produces incorrect results.

    • Due to flaws in the logic of the code.

    • Example: Incorrect formula in a calculation.

AttributeError analysis

Well if says the error occurred at line 34 so lets start there:

self.content_panel.clear() → clear content_panel in self (this component).

You can see that the self is the problem. It refers to the component the code resides in (in this case the SetDetailsComponent), when we actually want to refer to MainForm where content_panel resides.

So we need a way to refer to the MainForm from with in the SetDetailsComponent code. Luckily Anvil provide a command to do this → anvil.get_open_form()

Using the open form

The Anvil command anvil.get_open_form() returns the current open form, in our case it will be MainForm. This means we can get the MainForm, store it in a variable (main_form). This will enable fixing the code we just pasted by replacing self with main_form.

Make the changes highlighted below.

17  def button_save_click(self, **event_args):
18    
19    if self.text_box_first_name.text == "":
20      self.label_error.text = "First name cannot be blank"
21      self.label_error.visible = True
22      return
23
24    if self.text_box_last_name.text == "":
25      self.label_error.text = "Last name cannot be blank"
26      self.label_error.visible = True
27      return
28
29    self.label_error.visible = False
30    anvil.server.call("update_user", 
31                      self.text_box_first_name.text, 
32                      self.text_box_last_name.text)
33
34    main_form = get_open_form()
35    main_form.content_panel.clear()
36    main_form.content_panel.add_component(AccountComponent())
37    main_form.label_title.text = main_form.breadcrumb_stem + " - Account"
38    main_form.set_active_link(("account"))

Test again

Lets test again. The erroneous code came after writing the details to the User table, so you will need to delete those details to test again. then launch your website.

Now launch your website for testing:

  1. Register another user

  2. Enter their first name and last name

  3. Click Save Details

  4. WHAT AGAIN???

We still have an error. But look at the error closely, it’s a different, so that’s progress.

account component error

NameError analysis

This error points to line 36.

main_form.content_panel.add_component(AccountComponent()) → in the content_panel of the MainForm load the AccountComponent

It’s complaining because there is no AccountComponent in the SetDetailsComponent. We resolved this issue in the MainForm by importing the AccountComponent using the following line:

from ..AccountComponent import AccountComponent

So we need to add this to the import statement at the top of SetDetailsComponent.

Importing AccountComponent

Open the SetDetailsComponent in code mode an then add the highlighted code below:

1from ._anvil_designer import SetDetailsComponentTemplate
2from anvil import *
3import anvil.server
4import anvil.tables as tables
5import anvil.tables.query as q
6from anvil.tables import app_tables
7import anvil.users
8from ..AccountComponent import AccountComponent

Third test lucky

Again, delete the user you just added and launch your website.

  1. Register another user

  2. Enter their first name and last name

  3. Click Save Details

  4. You should now be on the AccountComponent, stop your website and check that the user details have been saved to the User table

Now that is all working, we have to add details to the AccountComponent.

Final code state

By the end of this tutorial your code should be the same as below:

Final SetDetailsComponent

 1from ._anvil_designer import SetDetailsComponentTemplate
 2from anvil import *
 3import anvil.server
 4import anvil.tables as tables
 5import anvil.tables.query as q
 6from anvil.tables import app_tables
 7import anvil.users
 8from ..AccountComponent import AccountComponent
 9
10
11class SetDetailsComponent(SetDetailsComponentTemplate):
12  def __init__(self, **properties):
13    # Set Form properties and Data Bindings.
14    self.init_components(**properties)
15
16    # Any code you write here will run before the form opens.
17
18  def button_save_click(self, **event_args):
19    
20    if self.text_box_first_name.text == "":
21      self.label_error.text = "First name cannot be blank"
22      self.label_error.visible = True
23      return
24
25    if self.text_box_last_name.text == "":
26      self.label_error.text = "Last name cannot be blank"
27      self.label_error.visible = True
28      return
29
30    self.label_error.visible = False
31    anvil.server.call("update_user", 
32                      self.text_box_first_name.text, 
33                      self.text_box_last_name.text)
34
35    main_form = get_open_form()
36    main_form.content_panel.clear()
37    main_form.content_panel.add_component(AccountComponent())
38    main_form.label_title.text = main_form.breadcrumb_stem + " - Account"
39    main_form.set_active_link(("account"))