SetDetailsComponent Code

Now we have the SetDetailsComponent layout complete, it is time to start working on the code. This code will:

  • Check that both the First name and Last name text boxes contain text

  • Display an error message if either text box is empty

  • Prints a message to terminal displaying the info that would be sent to the User table (this will be built on in the next tutorial)

Save Button Code

Create Handler

The code for this component will reside within the Save button click handler. We start by:

  1. clicking on the Save button

  2. selecting … on click event

  3. choosing the Code mode

create handler

Check First name text box

First we will check that the First name text box is not blank. We will use a guard clause to achieve this. Basically it is an if statement that will use return to end the method if the the text box is empty. This will prevent the unnecessarily executing the rest of the method’s code.

Guard clauses

Guard clauses are used in programming to check conditions at the start of a function. If the condition is True, the function stops right there.

Guard clauses offer several benefits in programming:

  • Improved Readability: They make the code easier to read by clearly showing conditions at the start of a function, allowing the main logic to follow without deep nesting.

  • Reduced Complexity: By removing unnecessary else blocks and nested if statements, guard clauses reduce code complexity, making it simpler and more straightforward.

  • Early Exit: They allow functions to exit early when conditions aren’t met, which can enhance performance and prevent errors later in the code.

  • Better Maintenance: With clearer code, maintenance becomes easier, as the logic is more apparent and debugging is simplified.

In the button_save_click hander, remove the comment and the pass statement, then add the highlighted code.

16  def button_save_click(self, **event_args):
17    
18    if self.text_box_first_name.text == "":
19      self.label_error.text = "First name cannot be blank"
20      self.label_error.visible = True
21      return

Code explaination

  • line 18:

    • self.text_box_first_name.text → get the current value of the text in text_box_first_name

      • note: placeholders aren’t considered text

    • == "" check if that text value is an empty string (nothing)

  • line 19:

    • self.label_error.text → change the text of the error message label to inform user that first name is missing.

  • line 20:

    • self.label_error.visible = True → make the error message label visible

  • line 21:

    • return → stop executing this method by returning controll to the main loop

Check Last name text box

The obvious next step is to repeat this process for the Last name text box.

Try and work out the code yourself before looking at the code below.

16  def button_save_click(self, **event_args):
17    
18    if self.text_box_first_name.text == "":
19      self.label_error.text = "First name cannot be blank"
20      self.label_error.visible = True
21      return
22
23    if self.text_box_last_name.text == "":
24      self.label_error.text = "Last name cannot be blank"
25      self.label_error.visible = True
26      return

Save message

Once the user has passed both guard clauses, we want to save the details to the User table. We will write the code for this next tutorial, but in the meanwhile we need to test this code. So rather than writtng the results to the User table we will print them to the terminal. We also need to hide the error message.

Add the highlighted code to the button_save_click handler.

16  def button_save_click(self, **event_args):
17    
18    if self.text_box_first_name.text == "":
19      self.label_error.text = "First name cannot be blank"
20      self.label_error.visible = True
21      return
22
23    if self.text_box_last_name.text == "":
24      self.label_error.text = "Last name cannot be blank"
25      self.label_error.visible = True
26      return
27
28    self.label_error.visible = False
29    print(self.text_box_first_name.text, self.text_box_last_name.text)

Code explaination

  • line 28:

    • self.label_error.visible = False → hides the error message

  • line 29:

    • self.text_box_first_name.text → current value of text_box_first_name

    • self.text_box_last_name.text → current value of text_box_last_name

    • print → display in the terminal

Redirect Register

Currently, when a user finish registering, we load the HomeComponent, we will need to change that to loading the SetDetailsComponent.

Open the MainForm in code mode.

First we need to import the SetDetailsComponent. So in the import section, add the highlighted code.

 1from ._anvil_designer import MainFormTemplate
 2from anvil import *
 3import anvil.tables as tables
 4import anvil.tables.query as q
 5from anvil.tables import app_tables
 6import anvil.users
 7from ..HomeComponent import HomeComponent
 8from ..CalendarComponent import CalendarComponent
 9from ..AddComponent import AddComponent
10from ..AccountComponent import AccountComponent
11from ..SetDetailsComponent import SetDetailsComponent

Change the link_register_click handler by replacing line 72-74 with the highlighted code below

69  def link_register_click(self, **event_args):
70    anvil.users.signup_with_form(allow_cancel=True)
71    self.content_panel.clear()
72    self.content_panel.add_component(SetDetailsComponent())
73    self.label_title.text = self.breadcrumb_stem + " - Account - Details"
74    self.set_active_link("details")

Testing

Before testing, we need to remove the last user you registered. So go to the Users table and delete all rows then launch your website:

Testing:

  1. Register a new account

  2. Leave the First name text box blank and click Save Details → should produce error

  3. Leave the Last name text box blank and click Save Details → should produce error

  4. Click save with both First name and Last name entered, the error message should disappear and their values should appear in the terminal

test

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
 8
 9
10class SetDetailsComponent(SetDetailsComponentTemplate):
11  def __init__(self, **properties):
12    # Set Form properties and Data Bindings.
13    self.init_components(**properties)
14
15    # Any code you write here will run before the form opens.
16
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    print(self.text_box_first_name.text, self.text_box_last_name.text)

Final MainForm

 1from ._anvil_designer import MainFormTemplate
 2from anvil import *
 3import anvil.tables as tables
 4import anvil.tables.query as q
 5from anvil.tables import app_tables
 6import anvil.users
 7from ..HomeComponent import HomeComponent
 8from ..CalendarComponent import CalendarComponent
 9from ..AddComponent import AddComponent
10from ..AccountComponent import AccountComponent
11from ..SetDetailsComponent import SetDetailsComponent
12
13
14class MainForm(MainFormTemplate):
15  def __init__(self, **properties):
16    # Set Form properties and Data Bindings.
17    self.init_components(**properties)
18    self.breadcrumb_stem = self.label_title.text
19
20    # Any code you write here will run before the form opens.
21    self.content_panel.add_component(HomeComponent())
22    self.set_active_link("home")
23
24  def set_active_link(self, state):
25    if state == "home":
26      self.link_home.role = "selected"
27    else:
28      self.link_home.role = None
29    if state == "add":
30      self.link_add.role = "selected"
31    else:
32      self.link_add.role = None
33    if state == "calendar":
34      self.link_calendar.role = "selected"
35    else:
36      self.link_calendar.role = None
37
38    self.link_register.visible = not anvil.users.get_user()
39    self.link_login.visible = not anvil.users.get_user()
40    self.link_account.visible = anvil.users.get_user()
41    self.link_logout.visible = anvil.users.get_user()
42  
43  # --- link handlers
44  def link_home_click(self, **event_args):
45    self.content_panel.clear()
46    self.content_panel.add_component(HomeComponent())
47    self.label_title.text = self.breadcrumb_stem
48    self.set_active_link("home")
49
50  def link_calendar_click(self, **event_args):
51    self.content_panel.clear()
52    self.content_panel.add_component(CalendarComponent())
53    self.label_title.text = self.breadcrumb_stem + " - Calendar"
54    self.set_active_link("calendar")
55
56  def link_add_click(self, **event_args):
57    self.content_panel.clear()
58    self.content_panel.add_component(AddComponent())
59    self.label_title.text = self.breadcrumb_stem + " - Add"
60    self.set_active_link("add")
61
62  def link_account_click(self, **event_args):
63    """This method is called when the link is clicked"""
64    self.content_panel.clear()
65    self.content_panel.add_component(AccountComponent())
66    self.label_title.text = self.breadcrumb_stem + " - Account"
67    self.set_active_link(("account"))
68
69  def link_register_click(self, **event_args):
70    anvil.users.signup_with_form(allow_cancel=True)
71    self.content_panel.clear()
72    self.content_panel.add_component(SetDetailsComponent())
73    self.label_title.text = self.breadcrumb_stem + " - Account - Details"
74    self.set_active_link("details")
75
76  def link_login_click(self, **event_args):
77    anvil.users.login_with_form(allow_cancel=True)
78    self.content_panel.clear()
79    self.content_panel.add_component(HomeComponent())
80    self.label_title.text = self.breadcrumb_stem
81    self.set_active_link("home")
82
83  def link_logout_click(self, **event_args):
84    anvil.users.logout()
85    self.content_panel.clear()
86    self.content_panel.add_component(HomeComponent())
87    self.label_title.text = self.breadcrumb_stem
88    self.set_active_link("home")