0
votes

Background

I am trying to make a dynamic navigation component in AEM. Currently I have been trying to find information in the docs and online to help me but have not been able to find much.

My application loads vue components into AEM so the front end is controlled by VUE and the data is passed in through props.

I would like to pass the pages and sub pages of those pages into the vue component, so I can create a dynamic navigation with a drop down nav for any links.

Example

Currently I found a way to use a java class to load the root pages links. I am doing that like this,

package services.agro.something.core.models;

import java.util.*;
import java.util.Iterator;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageFilter;

import com.adobe.cq.sightly.WCMUsePojo;

public class SidebarNavigationModel extends WCMUsePojo{
    private List<Page> items = new ArrayList<Page>();
    private Page rootPage;

    // Initializes the navigation
    @Override
    public void activate() throws Exception {
        rootPage = getCurrentPage().getAbsoluteParent(2);

        if (rootPage == null) {
            rootPage = getCurrentPage();
        }

        Iterator<Page> childPages = rootPage.listChildren(new PageFilter(getRequest()));
           while (childPages.hasNext()) {
            items.add(childPages.next());
           }
    }

    // Returns the navigation items
    public List<Page> getItems() {
        return items;
    }
    // Returns the navigation root
    public Page getRoot() {
        return rootPage;
    }
}

Then I could use this data like this,

   <div data-sly-use.sidebarNavigationModel="services.agro.gde.core.models.SidebarNavigationModel" class="sidebar-navigation ae-spacing-indent">
    <div class="sidebar-nav-container">
        // This is a vue component that I am trying to pass data to. The data comes through as commas and when I expect an array an error throws in console stating it expects array but receives a string.
        <sidebar-navigation title="${properties.title}" items="${sidebarNavigationModel.items}"></sidebar-navigation>
    </div>
    // This outputs 16 commas to the screen ${sidebarNavigationModel.items}
    <ul class="nav navbar-nav navbar-center">
        // This outputs a link to home
        <li><a href="${sidebarNavigationModel.root.path}.html">HOME</a></li>
        // This outputs 19 links like I expect
        <li class="nav navbar-nav navbar-left" data-sly-repeat="${sidebarNavigationModel.items}">
            <a href="${item.path}.html">${item.title}</a>
        </li>
    </ul>
</div>

Question

If I could better understand the data set that is returned in the loop I believe I could pass it to the vue component as I have tried.

Why does this output commas when outside of the loop and why when passing it to vue does it appears to be a string?

How can I get the sub pages for a site when it loads into a data set I can pass to my vue component from the template?

2

2 Answers

1
votes

HTL/Sightly is trying to render the array but for each item it will render nothing (since it cannot evaluate and render the Page object). What you could do is either massage the data in your Use-Object to return exactly the needed string or process it in the script like:

[<sly data-sly-repeat="${logic.items}">{title="${item.title}",path="${sidebarNavigationModel.path}"}${itemList.last?'':','}</sly>]
0
votes

The vue component is printing commas because the list returned by java class is a list of com.day.cq.wcm.api.Page objects and not a list of String. Sightly understands that it is a Page object and hence able to invoke page methods on it to retrieve path and title.

Getting a list of subpages - There are different ways you can do this. Depends a lot on your content structure and your requirement - what you consider are child and parent pages.

  • You can set an attribute in page properties for all the parents pages and use this attribute to identify a parent page and then construct a map of parent - child pages.
  • Or if your content structure runs more than a level deep and you need child pages from deep down the heirarchy, you can recursively fetch all the child pages and format into a data structure your vue component understands.
  • Or you could use Page API's like hasChild(), listChildren(), etc to drive your logic of constructing parent-child nav structure.

All this can be achieved from your java class.