Contents Menu Expand Light mode Dark mode Auto light/dark, in light mode Auto light/dark, in dark mode Skip to content
StudyM8
Logo
StudyM8

Contents:

  • Introduction
  • How websites work
  • StudyM8 design
  • Create new app
  • Anvil Interface
  • Create the Main Form
  • Adding Components
  • Connecting links
  • Set the Initial Component
  • Adjust Page Title
  • Show Active Link
  • Adding Users
  • User Management Features
  • Account Links Visibility
  • SetDetailsComponent Design
  • SetDetailsComponent Code
  • User Server Module
  • SetDetailsComponent Navigation
  • AccountComponent Layout
  • AccountComponent Code
  • Switch Component Method
  • Complete Account Component
  • The Assessments Table
  • AddComponent Design
  • AddComponent Code
  • Assessment Service Module
  • Prevent Unauthorised Access
  • HomeComponent Design
  • HomeComponent Code
  • Complete Assessments
  • Adjust Assessments Display
  • Edit Assessments Layout
  • Edit Assessments Code
  • CalendarComponent Layout
  • CalendarComponent Code
  • Welcome Page
  • Optimisation
  • Reduce Remote Database Access
  • Create Logout Function
  • Create Update User Function
  • My Assessments Function
  • Get Chart Function
  • Reduce Local Database Access
  • Resources
  • Topics
  • Licensing
Back to top
View this page

Show Active Link¶

In this tutorial you will:

  • Understand how to change a link’s role to indicate it is selected.

  • Apply roles using CSS classes for custom styling.

  • Implement state machines to manage component states.

  • Write efficient, non-repetitive code using the DRY principle.

  • Test links to ensure proper highlighting based on component load states.

In Material Design, we show active links to enhance the user experience and navigation. Highlighting active links provides users with a visual feedback indicating their current location within the website or application, offering a sense of context and orientation. Our website does not use active links, an issue that we will address in this tutorial.

Changing link’s roles¶

In Anvil, links can have a selected role. This changes the formatting of the link to differentiate it from non-selected links. It is the formatting that is uses when the mouse cursor moves over a link.

selected links

Roles

In Anvil, roles are used to apply specific CSS classes to components, allowing for customized styling and behavior. This makes it easy to target and style components using CSS, ensuring a consistent and manageable way to apply custom designs across your application

We want to use the selected role on the Home, Calendar and Add links, but only when their components are loaded. Each link has a property called role, so we need to set this value accordingly.

Role values for given state¶

To achieve this we are going to change the links role values according to the state of the website.

State Machine

A state machine is a way to design programs by breaking it down into different conditions called states. Each state represents a specific situation the program can be in. The program can switch from one state to another based on inputs or events. These switches are called transitions.

A state machine makes it easier to manage complex behaviors by clearly defining what the system should do in each state and how it moves between states.

Link State Logic table¶

State

link_home.role

link_calendar.role

link_add.role

HomeComponent loaded

selected

None

None

CalendarComponent loaded

None

selected

None

AddComponent loaded

None

None

selected

AccountComponent loaded

None

None

None

Code¶

The events that will change the website’s state are the clicking of links, so we could put the code in the event handlers. But that will require changing the link_home, link_calendar and link_add roles in each of the event handlers. This repetition of code violates the DRY principle.

DRY principle

The DRY (Don’t Repeat Yourself) principle in programming means that you should avoid writing the same code more than once. Instead, you write your code in a way that lets you use it in multiple places without copying and pasting it. This makes your code cleaner, easier to understand, and easier to change. If you need to update something, you only have to do it in one place, and it will automatically update everywhere else it’s used.

Instead we will create a seperate method that get called by each handler. When the handler calls the method, it will need to pass the state of the website.

Open the MainForm in code mode.

Lets place this method after the __init__ and before the link handlers, also add a structure comment identifying the link handlers.

18  def set_active_link(self, state):
19    pass
20  
21  # --- link handlers
22  def link_home_click(self, **event_args):

Code explaination

  • line 18:

    • def set_active_link → names the new method set_active_link

    • self → makes the method callable from within MainForm

    • state → expects the state of the website to be passed when called (this will be a string)

  • line 19:

    • pass → a placeholder that get replaced with our code.

  • line 21:

    • # --- link handlers → structural comment to help organise the code.

Now we will add the logic, which will be three if statements, one for each of the links. These if statements will follow the logic in our table above. We will identify the state of the machine by passing the following strings:

  • HomeComponent → "home"

  • CalendarComponent → "calendar"

  • AddComponent → "add"

  • AccountComponent → "account"

Home link¶

First we’ll do the home link.

18  def set_active_link(self, state):
19    if state == "home":
20      self.link_home.role = "selected"
21    else:
22      self.link_home.role = None

Code explaination

  • line 19:

    • if state == "home": → checks to see if “home” was passed as the state.

  • line 20 (only executed if state is “home”):

    • self.link_home.role = "selected" → changes the role (formatting) of home link to selected

  • line 22 (executed if the state is anything other than “home”)

    • self.link_home.role = None → changes the role (formatting) of home link back to the deselected (None)

Now we need to call set_active_link from the link_home_click event handler.

33  def link_home_click(self, **event_args):
34    self.content_panel.clear()
35    self.content_panel.add_component(HomeComponent())
36    self.label_title.text = self.breadcrumb_stem
37    self.set_active_link("home")

Code explaination

  • line 37:

    • self.set_active_link("home") → call the set_active_link method and pass the state “home”

Test home link¶

Launch your website and check if the Home link remains lighlighted once you click it.

home test

Calendar and Add links¶

Now your turn. Do the same for the Calendar link and Add link. Below is what your test should look like.

Calendar and add test

Notice that clicking on the Account link didn’t deselect the other link? Lets fix that

Account link¶

The Account link is a little different to the others. We don’t want to set it to selected, just deselect the other links. Look at the set_active_link method, the code is designed that if the link’s state is not passed, it will be deselected. So we can pass a state of “account” and all links will be deselected.

So, in the link_account_click handler call the set_active_link method and pass “account” as the state.

Now launch your website and check if the account link deselects the other links.

account test

Initial Component¶

In the lastest test you can notice that the Home link is not selected when the website launches. This is a simple fix.

Go to the __init__ and add a call to set_active_link just after you add the HomeComponent.

Testing¶

Test your website. Check that the Home link is selected when it load. then click on all four links we have worked on:

  • Home

  • Calendar

  • Add

  • Account

Did they all act as expected?

final test

Final code state¶

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

Final MainForm¶

 1from ._anvil_designer import MainFormTemplate
 2from anvil import *
 3from ..HomeComponent import HomeComponent
 4from ..CalendarComponent import CalendarComponent
 5from ..AddComponent import AddComponent
 6from ..AccountComponent import AccountComponent
 7
 8
 9class MainForm(MainFormTemplate):
10  def __init__(self, **properties):
11    # Set Form properties and Data Bindings.
12    self.init_components(**properties)
13    self.breadcrumb_stem = self.label_title.text
14
15    # Any code you write here will run before the form opens.
16    self.content_panel.add_component(HomeComponent())
17    self.set_active_link("home")
18
19  def set_active_link(self, state):
20    if state == "home":
21      self.link_home.role = "selected"
22    else:
23      self.link_home.role = None
24    if state == "add":
25      self.link_add.role = "selected"
26    else:
27      self.link_add.role = None
28    if state == "calendar":
29      self.link_calendar.role = "selected"
30    else:
31      self.link_calendar.role = None
32  
33  # --- link handlers
34  def link_home_click(self, **event_args):
35    self.content_panel.clear()
36    self.content_panel.add_component(HomeComponent())
37    self.label_title.text = self.breadcrumb_stem
38    self.set_active_link("home")
39
40  def link_calendar_click(self, **event_args):
41    self.content_panel.clear()
42    self.content_panel.add_component(CalendarComponent())
43    self.label_title.text = self.breadcrumb_stem + " - Calendar"
44    self.set_active_link("calendar")
45
46  def link_add_click(self, **event_args):
47    self.content_panel.clear()
48    self.content_panel.add_component(AddComponent())
49    self.label_title.text = self.breadcrumb_stem + " - Add"
50    self.set_active_link("add")
51
52  def link_account_click(self, **event_args):
53    """This method is called when the link is clicked"""
54    self.content_panel.clear()
55    self.content_panel.add_component(AccountComponent())
56    self.label_title.text = self.breadcrumb_stem + " - Account"
57    self.set_active_link(("account"))
Next
Adding Users
Previous
Adjust Page Title
Copyright © 2024, Damien Murtagh
Made with Sphinx and @pradyunsg's Furo
On this page
  • Show Active Link
    • Changing link’s roles
      • Role values for given state
        • Link State Logic table
    • Code
      • Home link
      • Test home link
      • Calendar and Add links
      • Account link
      • Initial Component
    • Testing
    • Final code state
      • Final MainForm