Dynamic Login / Logout menu items

Hello community

I’m trying to add some dynamic login / logout buttons to my anvil app. I’ve watched all the tutorials and read several forum posts around dynamically adding items etc. but just can’t quite get the logic right.

Here’s what I’m looking for:

I’ve got them working 80% of the time, but sometimes the click event will stop firing.

I’ll give you a view of how I’m doing it - it’s messy though…

I’m setting the Login and Logout links up in the form constructor (using the dashboard template) and then adding them dynamically to the sidebar slot

class MainForm (MainFormTemplate):
  def __init__(self, **properties):
    self.init_components(**properties)

    self.logout_button = Link(text="Logout")
    self.logout_button.set_event_handler("click", self.lnk_logout_click)
    
    self.login_button = Link(text="Login")
    self.login_button.set_event_handler("click", self.lnk_login_click)
    
    if anvil.users.get_user():
      print("Adding logout button on form load")
      self.add_component(self.logout_button, slot="sidebar")
    else:
      print("Adding login button on form load")
      self.add_component(self.login_button, slot="sidebar")

The events for handling clicks on logout button are:

  def logout(self):
    if anvil.users.get_user():
      self.content_panel.clear()
      anvil.users.logout()
      self.logout_button.remove_from_parent()
      self.add_component(self.login_button, slot="sidebar")
      self.content_panel.add_component(HomeForm())
    
  def lnk_logout_click (self, **event_args):
    if confirm("Are you sure you want to log out?"):
      self.logout()

and for handling clicks on login button:

  def do_login(self):
    if not anvil.users.get_user():
      if anvil.users.login_with_form():
        app_tables.log_logins.add_row(timestamp=datetime.datetime.now(), user=anvil.users.get_user())
        self.login_button.remove_from_parent()
        self.add_component(self.logout_button, slot="sidebar")
        return True
      else:
        return False
    elif anvil.users.get_user():
      return True

  def lnk_login_click (self, **event_args):
    self.do_login()

Then, I also call do_login() if another menu item (which I would expect to be authenticated) is clicked:

  def lnk_ccs_compare_click(self, **event_args):
    if self.do_login():
      self.content_panel.clear()
      self.content_panel.add_component(CCSCompareForm(), full_width_row = True)
    else:  
      pass

But I feel like I’ve got myself into a bit of a mess…

So has anyone done this successfully / better? or can anyone point me to resources I haven’t yet found that will help me work this out? :slight_smile:

1 Like

Oops! None of those things should cause the click event to stop firing - that was a bug in Anvil. I’ve fixed it, and it will be released in another day or two!

In the meantime, try setting the link’s visible property to False. It’s not ideal, visually speaking (you’ll still see the line separators), but normal service will be resumed shortly :slight_smile:

Thanks! I’ll just wait a couple of days for the new release :slight_smile:

@meredydd Thanks for fixing the event handlers :slight_smile:

1 Like