Dynamic Navigation in AEM using Sling Models and HTL
Tags: aem, webdev, javascript, tutorial
Published: 2023-03-11 21:38:44

Navigation is an important part of any website or application, allowing users to easily navigate between pages and access the content they're interested in. However, creating and maintaining a navigation menu can be a challenging task, especially for larger websites with many pages. In this article, we'll explore how to create a dynamic navigation menu in AEM using Sling Models and HTL.

**What is Sling Models?**

Sling Models is a powerful framework for creating Java-based models that map to AEM content. With Sling Models, you can easily create POJOs (Plain Old Java Objects) that represent AEM content and expose them as adaptable services to other components and templates.

Sling Models makes it easy to work with AEM content in a type-safe and efficient way, without having to deal with the complexities of the underlying JCR (Java Content Repository) API.

**What is HTL?**

HTL (HTML Template Language) is the recommended templating language for AEM, providing a lightweight and efficient way to generate HTML output from Sling Models and other data sources. HTL is easy to learn and use, and provides a number of powerful features for creating dynamic and responsive web pages.

Building a Dynamic Navigation Menu with Sling Models and HTL

To build a dynamic navigation menu in AEM, we'll need to follow a few key steps:

Create a Sling Model to represent the navigation data
Build an HTL template to display the navigation menu
Include the navigation menu in your page using the Sling Model and HTL template
Let's take a closer look at each step in turn.

**Step 1: Create a Sling Model for the Navigation Data**

The first step in building a dynamic navigation menu is to create a Sling Model that maps to the navigation data in AEM. In this example, we'll create a NavigationModel class that retrieves the current page and its siblings, and builds a list of NavigationItem objects that represent each page in the navigation menu.

Here's an example implementation of the NavigationModel class:

```
@Model(adaptables = Resource.class)
public class NavigationModel {
    
    @Inject
    private PageManager pageManager;
    
    private List<NavigationItem> items;
    
    @PostConstruct
    protected void init() {
        Page currentPage = pageManager.getContainingPage(context.resource());
        if (currentPage != null) {
            items = buildNavigation(currentPage);
        }
    }
    
    public List<NavigationItem> getItems() {
        return items;
    }
    
    private List<NavigationItem> buildNavigation(Page currentPage) {
        List<NavigationItem> navigationItems = new ArrayList<>();
        Iterator<Page> siblings = currentPage.listChildren();
        while (siblings.hasNext()) {
            Page sibling = siblings.next();
            if (sibling.isVisible()) {
                navigationItems.add(new NavigationItem(sibling));
            }
        }
        return navigationItems;
    }
    
    public static class NavigationItem {
        private String title;
        private String url;
        private boolean isActive;
        private List<NavigationItem> children;
        
        public NavigationItem(Page page) {
            this.title = page.getTitle();
            this.url = page.getPath() + ".html";
            this.isActive = page.isSelf(currentPage);
            if (page.listChildren().hasNext()) {
                this.children = buildNavigation(page);
            }
        }
        
        // Getters for title, url, isActive, and children
    }
}

```

In this code, we create a Sling Model called `NavigationModel that uses the @Model annotation to mark the class as a Sling Model. We inject a PageManager object to retrieve the current page and its siblings, and use the @PostConstruct annotation to initialize the items list with the results of the buildNavigation method.

The buildNavigation method iterates over the siblings of the current page, creates a NavigationItem object for each visible sibling, and adds it to the navigationItems list. If the sibling page has children, the method recursively calls itself to build a nested navigation menu.

The NavigationItem class represents a single item in the navigation menu, and includes properties for the item's title, URL, whether it is currently active, and any child navigation items.

**Step 2: Build an HTL Template to Display the Navigation Menu**

With our Sling Model in place, we can now create an HTL template that displays the navigation menu. The template will use the data-sly-use attribute to include the NavigationModel Sling Model, and will iterate over the items list to generate the HTML for each navigation item.

Here's an example HTL template for the navigation menu:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w36i06bu4aej95hco98e.jpg)


In this code, we use the data-sly-use attribute to include the NavigationModel Sling Model, and create a navigation variable that maps to the Sling Model instance. We then use the data-sly-repeat attribute to iterate over the items list, and generate HTML for each navigation item.

The data-sly-if attribute is used to check if the current navigation item has any child navigation items, and if so, generate a nested ul element for the child items.

**Step 3: Include the Navigation Menu in Your Page**

With our Sling Model and HTL template in place, we can now include the navigation menu in our page. To do this, we'll need to create a new component that includes the HTL template and exposes the NavigationModel Sling Model as an adaptable service.

Here's an example implementation of the navigation component:

`/apps/myproject/components/navigation
    - navigation.html
    - NavigationModel.java`

In this code, we create a new AEM component called navigation under the /apps/myproject/components directory. The component includes two files: navigation.html, which contains the HTL template, and NavigationModel.java, which contains the Sling Model implementation.

To include the navigation menu in a page, we can simply drag-and-drop the navigation component onto the page in AEM's edit mode. The component will render the navigation menu using the HTL template and the NavigationModel Sling ModelOnce we have added the navigation component to our page, we can preview the page to see the navigation menu in action. The menu will dynamically display the current page and its siblings, along with any child navigation items.

If we need to customize the behavior or appearance of the navigation menu, we can modify the NavigationModel Sling Model or the HTL template as needed. For example, we might add support for multi-level navigation menus, or modify the HTML structure of the menu to better match our design.

By using a Sling Model and an HTL template, we can create a dynamic and flexible navigation menu that is easy to customize and maintain. The Sling Model separates the logic for building the navigation menu from the presentation layer, while the HTL template provides a flexible and powerful way to generate HTML output based on the Sling Model data.

Overall, this approach can help us create more maintainable and reusable components in AEM, and can simplify the process of building complex UI elements like navigation menus.