Disable repeating panel component ONLY when associated radio button is selected

I have a repeating panel with a radio button and a check box in each row. I want to make it so that when the radio button is selected, the checkbox in that row is disabled, and when the radio button is not selected, the checkbox is enabled.

I have tried adding the ‘radio_button_1_clicked’ event, but this only seems to fire when a radio button is selected. NOT when it is deselected. So the following code just disables the checkbox, and it can then never be re-enabled.

  def radio_button_1_clicked(self, **event_args):
    """This method is called when this radio button is selected"""
    if self.radio_button_1.selected == True:
      self.check_box_1.enabled = False
    if self.radio_button_1.selected == False:
      self.check_box_1.enabled = True

Is there any way to make it so that the check box will be re-enabled when the radio button is deselected?

Do I understand correctly that the radio_button would get de-selected by clicking a different radio button in the repeating panel? If so, here’s a sketch of an idea: you could use the structure suggested here to raise an event on the parent repeating panel whenever a button is clicked. Set the event handler on the repeating panel to call a self.enable_all_check_boxes method.

Can you elaborate a little bit? Do I have to define enable_all_check_boxes somehow? When I added self.parent.enable_all_check_boxes to the radio button clicked event, I get the error: ‘RepeatingPanel’ object has no attribute ‘enable_all_check_boxes’

1 Like

You want one of the repeating panel rows to trigger an event in the other repeating panel rows. The most straightforward way of doing that is something like:

self.parent.raise_event_on_children('x-yourcustomeventname', self.item)

Your repeating panel rows would need to set an event handler in their init methods, and tie your custom event to an event handling function in the repeating panel row. That function could check the item passed in to see if it’s that row or not, and do whatever is appropriate.

This section of the docs mentioned raise_event_on_children: Anvil Docs | Anvil Components

And this one talks about custom events: Anvil Docs | Anvil Components

1 Like

Thanks. I think I’ve got the idea, but it’s still just disabling the checkboxes and never re-enabling them. Here’s what I have in my ItemTemplate code:

class ItemTemplate1(ItemTemplate1Template):
  def __init__(self, **properties):
    # Set Form properties and Data Bindings.
    self.init_components(**properties)
    self.label_1.text = self.item
    self.check_box_1.enabled = False
    self.set_event_handler('x-enable_checkbox', self.enable_checkbox())

    # Any code you write here will run when the form opens.

  def enable_checkbox(self, **event_args):
    self.check_box_1.enabled = True
    print('foo '+self.label_1.text)
    
  def radio_button_1_clicked(self, **event_args):
    """This method is called when this radio button is selected""" 
    self.parent.raise_event_on_children('x-enable_checkbox')
    self.check_box_1.enabled = False

I made it so the checkboxes are disabled by default, and when the event handler is added, it does enable all the checkboxes, so I know the event works properly. And I added a print statement to see when the event gets raised. Looks like it’s just not getting raised in the radio_button_1_clicked event. Does raise_event_on_children actually execute the event on each row? Seems like that’s maybe not how this works?

Raise event does execute the event in each row, but in your case you’re calling the function when you add the event handler, and not allowing Anvil to call it when you raise the event. You want it without the parenthesis after self.enable_checkbox:

self.set_event_handler('x-enable_checkbox', self.enable_checkbox)

As is, though, that will just enable all the checkboxes when you click any radio button. If I understand what you originally posted, you want the checkbox that matches the radio button to be enabled, and all the others ones to be disabled. You need to pass information to the event telling it which radio button was clicked, something like:

def radio_button_1_clicked(self, **event_args):
    """This method is called when this radio button is selected""" 
    self.parent.raise_event_on_children('x-enable_checkbox', item=self.item)

And then in your event handling code, look at that parameter to see what you need to do:

  def enable_checkbox(self, item, **event_args):
    self.check_box_1.enabled = item == self.item
2 Likes

Thank you!! Removing the parentheses did it. And don’t worry, this now works as intended. Because it happens in sequence, first any checkbox that was disabled gets re-enabled, and then the checkbox next to the radio button gets disabled. Result is that only a single checkbox can be disabled at a time. Here’s the final code in case it is ever useful for anyone:

class ItemTemplate1(ItemTemplate1Template):
  def __init__(self, **properties):
    # Set Form properties and Data Bindings.
    self.init_components(**properties)
    self.label_1.text = self.item
    self.set_event_handler('x-enable_checkbox', self.enable_checkbox)

    # Any code you write here will run when the form opens.
    
  def enable_checkbox(self, **event_args):
    self.check_box_1.enabled = True
  
  def radio_button_1_clicked(self, **event_args):
    """This method is called when this radio button is selected""" 
    self.parent.raise_event_on_children('x-enable_checkbox')
    self.check_box_1.enabled = False

Thanks again!
3 Likes