Validation on edit form with alert

Hi,

I’m using an alert with a custom form to provide an edit view as per https://anvil.works/learn/tutorials/database-backed-apps/chapter-4

I’m trying to work out how I can do validation on the data entry so that it’s not possible to ‘save’ a record unless all validation passes. I know I can do validation in line using events on the text boxes, but what I’m really after is a way to do blocking validation when they click ‘Save’.

I can get it validating on Save, and popping up an alert to say it doesn’t pass etc. but it still ends up closing the alert, so they just lose the data they’ve already entered.

Is there a way to do data validation when someone clicks the Save button, either before the form is dismissed and the Save is processed OR to somehow do the validation and then re-display the form with the entered data if it doesn’t pass?

Here’s the code launching the alert, and processing the Save click. I’m launching this from a button click in a DataRowPanel within a DataGrid.

  def btn_edit_click(self, **event_args):
    # Get the index of the data item in the list, so that we can easily replace it by index on save
    item_index = next((index for (index, d) in enumerate(Globals.data_list) if d["id"] == self.item['id']), None)
    self.current_index = item_index
    
    data_item = self.item
    
    save_clicked = alert(
      content=SiteEdit(item= data_item),
      title="Edit Site",
      large=True,
      buttons=[("Save", True), ("Cancel", False)],
    )

    if save_clicked:

            #  I'd like to do data validation here, and only save the item if it passes. 
            #  If it fails, I'd like to re-display the custom form with the data they've already entered so they can correct it
            if data_valid == True:
                self.item = data_item
            else:
                redisplay_form()

I did wonder if I could use https://anvil.works/library/form-validation however I can’t work out how to disable the “Save” button on the alert form as they are built in to the alert?

For this sort of thing, I add my own buttons to the form itself and pass buttons=[] to the alert function.

You can then do whatever you like when your buttons are clicked and control the closure of the alert using events. You can also use the validation library to control when your buttons are enabled.

Relevant part of the docs is: https://anvil.works/docs/client/python/alerts-and-notifications#custom-popup-content

4 Likes

Hi @mattstibbs,

There are two approaches here. The first is as @owen.campbell suggests - to move the interaction into the pop-up, and only close when validation is satisfied.

The other is to apply validation after closing, and then re-show the same components so they can correct their error. The trick here is to keep your instance of SiteEdit around, and re-show that same object in an alert when the validation fails. Something like:

  def btn_edit_click(self, **event_args):
    # Get the index of the data item in the list, so that we can easily replace it by index on save
    item_index = next((index for (index, d) in enumerate(Globals.data_list) if d["id"] == self.item['id']), None)
    self.current_index = item_index
    
    data_item = self.item
    site_edit = SiteEdit(item=data_item)
    valid = False

    while not valid:
      save_clicked = alert(
        content=site_edit,
        title="Edit Site",
        large=True,
        buttons=[("Save", True), ("Cancel", False)],
      )
      if not save_clicked:
        break

      valid = # ... work out whether the data is valid ...
      if not valid:
        alert("You need to type more things into the boxes")
5 Likes

Thanks! I like the while loop method, and saves having to recreate the buttons so feels a little easier.

Should this be passing site_edit In to the content= parameter in order to make use of the same option?

1 Like

Oh, you’re quite right – thanks for spotting that! I’ve updated the code sample :slight_smile:

1 Like