Chapter 3:
Write client-side Python

We want to receive an email when users click the ‘Submit’ button. This means calling the send_feedback server function when our users click the submit_feedback Button.

We’ll use Events for this.

Step 1: Set up an event handler

Anvil components can raise events. For example, when a Button is clicked, it raises the ‘click’ event.

Click on our ‘Submit’ Button, and click on click event -> in the Object Palette.

Configuring a click event handler for a Button using the Properties Panel

We will be taken to the Form Editor’s ‘Code’ view, where we’ll see the Code Editor. This is where we write our client-side Python code that runs in the browser.

For a full explanation of the difference between client-side and server-side Python, and why we write code for Anvil apps in two different places, check out our client-server architecture guide.

We’ll see a submit_button_click method that looks like this:

  def submit_button_click(self, **event_args):
    """This method is called when the button is clicked"""
    pass

This is the Python method that runs when the ‘Submit’ Button is clicked.

For example, let’s display a simple popup with the text ‘You clicked the button’ when the button is clicked. We’ll edit our submit_button_click function as follows:

  def submit_button_click(self, **event_args):
    # Display a popup that says 'You clicked the button'
    alert("You clicked the button")

Step 2: Run your app

To see it in action, click the ‘Run’ button at the top of the screen:

Location of the 'Run' button

Click the Submit button and our popup should appear!

Step 3: Capture user inputs

When someone clicks Submit on our feedback form, we want to receive an email with the person’s name, email address, and some feedback.

To accomplish this, we can retrieve data from our input components by accessing their properties. For example, we can read the text in our TextBoxes using their text property.

Let’s edit our submit_button_click function to look like this:

def submit_button_click(self, **event_args):
  # Set 'name' to the text in the 'name_box'
  name = self.name_box.text
  # Set 'email' to the text in the 'email_box'
  email = self.email_box.text
  # Set 'feedback' to the text in the 'feedback_box'
  feedback = self.feedback_box.text

Great! We’ve now captured the name, email, and feedback that we want. Next, we’ll make our function pass the data to our send_feedback server function when the submit button is clicked.

To make the send_feedback server function available to our client-side code, we need to decorate it with @anvil.server.callable. Open the app’s server module and add the decorator.

@anvil.server.callable
def send_feedback(name, email, feedback):
  # Send yourself an email each time feedback is submitted
  anvil.email.send(to="noreply@anvil.works", # Change this to your email address!
                   subject=f"Feedback from {name}",
                   text=f"""
                   
  A new person has filled out the feedback form!

  Name: {name}
  Email address: {email}
  Feedback:
  {feedback}
  """)
By explicitly marking functions as callable from the client, Anvil ensures that only designated functions are available to the client-side. This helps prevent unintended exposure of server-side functionality to the client, thus enhancing security.

Returning to our client code, we can now call our send_feedback server function from within our submit_button_click function:

def submit_button_click(self, **event_args):
  name = self.name_box.text
  email = self.email_box.text
  feedback = self.feedback_box.text
  # Call your 'send_feedback' server function
  # pass in name, email and feedback as arguments
  anvil.server.call('send_feedback', name, email, feedback)

Step 4: Display a notification

We’ll also display a temporary popup using a Notification to let our users know their feedback has been submitted.

Let’s add Notification("Feedback submitted!").show() to the end of our submit_button_click function:

  def submit_button_click(self, **event_args):
    name = self.name_box.text
    email = self.email_box.text
    feedback = self.feedback_box.text
    anvil.server.call('send_feedback', name, email, feedback)
    # Show a popup that says 'Feedback submitted!'
    Notification("Feedback submitted!").show()

Step 5: Clear our user inputs

There’s one final step left, and that’s to clear our user inputs each time someone submits feedback.

We’ll do this in a separate function to keep our code nice and clean.

We’ll add this method to our Form, underneath our submit_button_click() method:

  def clear_inputs(self):
    # Clear our three text boxes
    self.name_box.text = ""
    self.email_box.text = ""
    self.feedback_box.text = ""

Finally, let’s call this from our submit_button_click method, so that we clear our inputs each time feedback is submitted.

Edit the submit_button_click function to look like this:

  def submit_button_click(self, **event_args):
    name = self.name_box.text
    email = self.email_box.text
    feedback = self.feedback_box.text
    anvil.server.call('send_feedback', name, email, feedback)
    Notification("Feedback submitted!").show()
    # Call your 'clear_inputs' method to clear the boxes
    self.clear_inputs()

Step 6: Run your app

Time to Run our app! Click the ‘Run’ button at the top of the screen, fill in a name, email address, and some feedback and click Submit.

Then, stop the app, and go to your email inbox. You’ll see you have a new feedback email!

Running the app, completing the inputs and clicking Submit, stopping the app and seeing the data stored in the Data Table

In Chapter 4, we’ll have our app store the feedback in a database.

Chapter complete

Congratulations! You’ve created an app to gather user feedback.

We’ll take it one step further: let’s store the feedback with Anvil’s built-in database.