Edit Assessments Code

Planning

The code is going to react to two events:

  • button_edit click

  • button_save click

So, lets go ahead and create those two event handlers.

Open the AssessmentPanel in Design mode:

  1. click on each button

  2. select on click event

event handlers

Code

Button edit click

When the user clicks the edit button, we want to web app to:

  • take the values of the assessment item from this specific panel and write them into the edit elements

  • make all the display element invisible

  • make all the edit elements visible

Open the AssessmentPanel in Code mode.

In the button_edit_click handler use the code below to copy the values from the display elements.

27  def button_edit_click(self, **event_args):
28    self.text_box_subject.text = self.item["subject"]
29    self.text_box_details.text = self.item["details"]
30    self.date_picker_start.date = self.item["start_date"]
31    self.date_picker_due.date = self.item["due_date"]

Code explaination

  • line 28 → takes subject value for specific assessment for this panel and saves it as the text for the subject text box.

  • line 29 → takes details value for specific assessment for this panel and saves it as the text for the details text box.

  • line 30 → takes start_date value for specific assessment for this panel and saves it as the date for the start date picker

  • line 31 → takes due_date value for specific assessment for this panel and saves it as the date for the due date picker

Now we need to change the visibility of the elements. To do this we will create a separate function that swaps the visibility of each element, ie. if visibility was True it will make it False.

We will do this with one function that will work for both event handlers. Add the highlighted code below to the bottom of the AssessmentPanel code.

33  def button_save_click(self, **event_args):
34    """This method is called when the button is clicked"""
35    pass
36    
37  def switch_components(self):
38    # display elements
39    self.label_subject.visible = not self.label_subject.visible
40    self.label_details.visible = not self.label_details.visible
41    self.label_start.visible = not self.label_start.visible
42    self.label_due.visible = not self.label_due.visible
43    self.button_edit.visible = not self.button_edit.visible
44    
45    # edit elements
46    self.text_box_subject.visible = not self.text_box_subject.visible
47    self.text_box_details.visible = not self.text_box_details.visible
48    self.date_picker_start.visible = not self.date_picker_start.visible
49    self.date_picker_due.visible = not self.date_picker_due.visible
50    self.button_save.visible = not self.button_save.visible

Code explaination

  • line 37 → create the switch_components method

  • lines 39 - 43 → swaps the visibility value for each of the display elements

  • lines 46 - 50 → swaps the visibility value for each of the edit elements

Finally, to call the switch_components method from the button_edit_click handler, add the highlighted code.

27  def button_edit_click(self, **event_args):
28    self.text_box_subject.text = self.item["subject"]
29    self.text_box_details.text = self.item["details"]
30    self.date_picker_start.date = self.item["start_date"]
31    self.date_picker_due.date = self.item["due_date"]
32    self.switch_components()

Code explaination

  • line 32 → called the switch_component method

Test the edit button

Launch your website and test if the edit button works. You may need to adjust the width of your columns to make everything fit.

edit button test

If you have fixed you column widths, then it is time to make the save button work.

Button save click

When the user clicks the Save button we want the following to happen:

  • take the values of all the edit elements and write them the Assessments table

  • take the values from the edit elements and write them to the display elements

  • make all the edit elements invisible

  • make all the display elements visible

assessment_update

To achieve the first step, we will need to call a backend function to save the values to the Assessments table. So open the assessments_service, and add the highlighted code to the end.

26@anvil.server.callable
27def update_assessment_completed(assessment_id, completed):
28  assessment = app_tables.assessments.get_by_id(assessment_id)
29  if assessment:
30    assessment["completed"] = completed
31
32@anvil.server.callable
33def update_assessment(assessment_id, subject, details, start_date, due_date, completed):
34    assessment = app_tables.assessments.get_by_id(assessment_id)
35    if assessment:
36        assessment['subject'] = subject
37        assessment['details'] = details
38        assessment['start_date'] = start_date
39        assessment['due_date'] = due_date
40        assessment['completed'] = completed

Code explaination

  • line 26 → makes this function callable by the frontend

  • line 27 → create the update_assessments function which requires the following data to be passed:

    • assessment_id

    • subject

    • details

    • start_date

    • due_date

    • completed

  • line 34 → loads the assessment that has the passed assessment_id

  • line 35 → checks to see if there is an assessment with the passed assessment_id

  • lines 36 - 40 → overwrites the stored values of the assessment with the values passed

Now that we have our backend function to call, we can work on the button_save_click handler.

button_save_click

Open the AssessmentPanel in code mode.

First thing we will do is write the values to the Assessments table. Go to the button_save_click handler and replace lines 35 and 36 with the highlighted code below:

34  def button_save_click(self, **event_args):
35    # write to server
36    anvil.server.call('update_assessment', 
37                     self.item.get_id(),
38                     self.text_box_subject.text,
39                     self.text_box_details.text,
40                     self.date_picker_start.date,
41                     self.date_picker_due.date,
42                     self.check_box_completed.checked)

Code explaination

  • line 35 → a comment to help structure the method

  • lines 36 - 42 → calls the function we just created in the assessment_service. The first argument needs to be the name of the function being called. The other arguments are the date the function needs passed.

  • line 37 → gets the id of the assessment for this specific panel.

Next we need to take all the values from the edit elements and write them to the display elements, so the display reflects the changes made.

Add the highlighted code to the end of the button_save_click event handler.

34  def button_save_click(self, **event_args):
35    # write to server
36    anvil.server.call('update_assessment', 
37                     self.item.get_id(),
38                     self.text_box_subject.text,
39                     self.text_box_details.text,
40                     self.date_picker_start.date,
41                     self.date_picker_due.date,
42                     self.check_box_completed.checked)
43
44    # update display
45    self.label_subject.text = self.text_box_subject.text
46    self.label_details.text = self.text_box_details.text
47    self.label_start.text = self.date_picker_start.date.strftime('%d/%m/%Y')
48    self.label_due.text = self.date_picker_due.date.strftime('%d/%m/%Y')

Code explaination

  • line 44 → a comment to help structure the method

  • line 45 → assigns the value in the subject text box to the subject label

  • line 46 → assigns the value in the details text box to the details label

  • line 47 → assigns the date in the start date picker to the start label

  • line 48 → assigns the date in the due date picker to the due label

Finally, we need to turn all the edit elements invisible and all the display elements visible. Luckily we created a method that swaps all those elements visibility values, so we can just call that.

34  def button_save_click(self, **event_args):
35    # write to server
36    anvil.server.call('update_assessment', 
37                     self.item.get_id(),
38                     self.text_box_subject.text,
39                     self.text_box_details.text,
40                     self.date_picker_start.date,
41                     self.date_picker_due.date,
42                     self.check_box_completed.checked)
43
44    # update display
45    self.label_subject.text = self.text_box_subject.text
46    self.label_details.text = self.text_box_details.text
47    self.label_start.text = self.date_picker_start.date.strftime('%d/%m/%Y')
48    self.label_due.text = self.date_picker_due.date.strftime('%d/%m/%Y')
49    self.switch_components()
  • line 49 → call the switch component method to reverse the visibility of the edit and display elements.

Testing

You should be able to change the values of your assessments. Launch your webapp, and try to change the details. Make sure that you test all values (subject, details, start date and due date).

Final code state

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

AssessmentPanel

 1from ._anvil_designer import AssessmentPanelTemplate
 2from anvil import *
 3import anvil.server
 4import anvil.users
 5import anvil.tables as tables
 6import anvil.tables.query as q
 7from anvil.tables import app_tables
 8import datetime
 9
10
11class AssessmentPanel(AssessmentPanelTemplate):
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    self.check_box_completed.checked = self.item['completed']
18    self.label_subject.text = self.item['subject']
19    self.label_details.text = self.item['details']
20    self.label_start.text = self.item['start_date'].strftime('%d/%m/%Y')
21    self.label_due.text = self.item['due_date'].strftime('%d/%m/%Y')
22
23  def check_box_completed_change(self, **event_args):
24    new_value = self.check_box_completed.checked
25    anvil.server.call('update_assessment_completed', self.item.get_id(),new_value)
26
27  def button_edit_click(self, **event_args):
28    self.text_box_subject.text = self.item["subject"]
29    self.text_box_details.text = self.item["details"]
30    self.date_picker_start.date = self.item["start_date"]
31    self.date_picker_due.date = self.item["due_date"]
32    self.switch_components()
33
34  def button_save_click(self, **event_args):
35    # write to server
36    anvil.server.call('update_assessment', 
37                     self.item.get_id(),
38                     self.text_box_subject.text,
39                     self.text_box_details.text,
40                     self.date_picker_start.date,
41                     self.date_picker_due.date,
42                     self.check_box_completed.checked)
43
44    # update display
45    self.label_subject.text = self.text_box_subject.text
46    self.label_details.text = self.text_box_details.text
47    self.label_start.text = self.date_picker_start.date.strftime('%d/%m/%Y')
48    self.label_due.text = self.date_picker_due.date.strftime('%d/%m/%Y')
49    self.switch_components()
50  
51  def switch_components(self):
52    # display elements
53    self.label_subject.visible = not self.label_subject.visible
54    self.label_details.visible = not self.label_details.visible
55    self.label_start.visible = not self.label_start.visible
56    self.label_due.visible = not self.label_due.visible
57    self.button_edit.visible = not self.button_edit.visible
58    
59    # edit elements
60    self.text_box_subject.visible = not self.text_box_subject.visible
61    self.text_box_details.visible = not self.text_box_details.visible
62    self.date_picker_start.visible = not self.date_picker_start.visible
63    self.date_picker_due.visible = not self.date_picker_due.visible
64    self.button_save.visible = not self.button_save.visible

assessment_service

 1import anvil.users
 2import anvil.tables as tables
 3import anvil.tables.query as q
 4from anvil.tables import app_tables
 5import anvil.server
 6
 7@anvil.server.callable
 8def add_assessment(subject, details, start_date, due_date):
 9  user = anvil.users.get_user()
10  
11  app_tables.assessments.add_row(user= user,
12                                 subject= subject,
13                                 details=details,
14                                 start_date=start_date,
15                                 due_date=due_date,
16                                 completed=False)
17
18@anvil.server.callable
19def get_assessment():
20  user = anvil.users.get_user()
21
22  return app_tables.assessments.search(tables.order_by('due_date'),
23                                      user=user,
24                                      completed=False)
25
26@anvil.server.callable
27def update_assessment_completed(assessment_id, completed):
28  assessment = app_tables.assessments.get_by_id(assessment_id)
29  if assessment:
30    assessment["completed"] = completed
31
32@anvil.server.callable
33def update_assessment(assessment_id, subject, details, start_date, due_date, completed):
34    assessment = app_tables.assessments.get_by_id(assessment_id)
35    if assessment:
36        assessment['subject'] = subject
37        assessment['details'] = details
38        assessment['start_date'] = start_date
39        assessment['due_date'] = due_date
40        assessment['completed'] = completed