Cannot access core sling model Navigation variables | Community
Skip to main content
Level 3
July 12, 2023
Solved

Cannot access core sling model Navigation variables

  • July 12, 2023
  • 2 replies
  • 1379 views

I replicated in my code the navigation core component that uses the path 

'com.adobe.cq.wcm.core.components.models.Navigation"
 
But I can't access the 'item' variable to display items that I need
 
Inside my nav tag I have 
data-sly-use.navigation="com.adobe.cq.wcm.core.components.models.Navigation"
 
And if I display ${navigation} it returns 
com.adobe.cq.wcm.core.components.internal.models.v2.NavigationImpl@77b55338
And if I display ${navigation.items} it returns com.adobe.cq.wcm.core.components.internal.models.v2.NavigationItemImpl@100833c1
 
 
 
This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.
Best answer by aanchal-sikka

@nathanvieira 

 

You can readily use all the existing code by using Delegation https://experienceleague.adobe.com/docs/experience-manager-core-components/using/developing/customizing.html?lang=en#customizing-the-logic-of-a-core-component

 

You just need to use @Via annotation. Following would not be required.

LinkManager
LocalizationUtils
Utils 

2 replies

aanchal-sikka
Community Advisor
Community Advisor
July 12, 2023

Hello @nathanvieira 

 

The WCM Core Sling Models are tied to specific resource types. Example:


public static final String RESOURCE_TYPE = "core/wcm/components/navigation/v1/navigation";

https://github.com/adobe/aem-core-wcm-components/blob/main/bundles/core/src/main/java/com/adobe/cq/wcm/core/components/internal/models/v2/NavigationImpl.java

 

When Navigation 2 component was created in WCM core component, a dummy v2 Sling Model was also created, which is an extension of v1 https://github.com/adobe/aem-core-wcm-components/blob/main/bundles/core/src/main/java/com/adobe/cq/wcm/core/components/internal/models/v2/NavigationImpl.java 

 

For your implementation, you might have to create a Model, that binds to your component and then use the WCM Core Navigation component via Delegate pattern.

 

 

Aanchal Sikka
Level 3
July 13, 2023

I was able to create my model and bind to my component, and I need the same variables that the core component Navigation uses. 

 

But i have these erros 

import com.adobe.cq.wcm.core.components.internal.Utils
(The import com.adobe.cq.wcm.core.components.internal cannot be resolved)
 
import com.adobe.cq.wcm.core.components.internal.LocalizationUtils;
(The import com.adobe.cq.wcm.core.components.internal cannot be resolved)
 
com.adobe.cq.wcm.core.components.commons.link.LinkManager
(The import com.adobe.cq.wcm.core.components.commons.link.LinkManager cannot be resolved)
 
I know I can't directtly access the file in the adobe internal folder but how can I fix these error and use 
 
LinkManager
LocalizationUtils
Utils 
Level 3
July 13, 2023
package com.myproject.core.models.impl; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; import javax.annotation.PostConstruct; import javax.mail.Quota.Resource; import com.adobe.cq.wcm.core.components.internal.Utils; import com.adobe.cq.wcm.core.components.util.AbstractComponentImpl; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.ValueMap; import org.apache.sling.models.annotations.Exporter; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.Via; import org.apache.sling.models.annotations.injectorspecific.OSGiService; import org.apache.sling.models.annotations.injectorspecific.ScriptVariable; import org.apache.sling.models.annotations.injectorspecific.Self; import org.apache.sling.models.annotations.via.ResourceSuperType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.adobe.cq.export.json.ComponentExporter; import com.adobe.cq.export.json.ExporterConstants; import com.adobe.cq.wcm.core.components.internal.LocalizationUtils; import com.adobe.cq.wcm.core.components.commons.link.LinkManager; import com.adobe.cq.wcm.core.components.models.Navigation; import com.adobe.cq.wcm.core.components.models.NavigationItem; import com.day.cq.wcm.api.LanguageManager; import com.day.cq.wcm.api.Page; import com.day.cq.wcm.api.PageFilter; import com.day.cq.wcm.api.components.Component; import com.day.cq.wcm.api.designer.Style; import com.day.cq.wcm.msm.api.LiveRelationshipManager; /** * Navigation model implementation. */ @Model(adaptables = SlingHttpServletRequest.class, adapters = {Navigation.class, ComponentExporter.class}, resourceType = {NavMenuHeaderImpl.RESOURCE_TYPE}) public class NavMenuHeaderImpl implements Navigation { /** * The resource navigation component resource type. */ public static final String RESOURCE_TYPE = "apps/myproject/components/atom_nav-header"; /** * Name of the resource / configuration policy property that defines the accessibility label. */ private static final String PN_ACCESSIBILITY_LABEL = "accessibilityLabel"; /** * The current request. */ @Self private SlingHttpServletRequest request; /** * The link manager. */ @Self private LinkManager linkManager; /** * The current page. */ @ScriptVariable private Page currentPage; /** * The current style. */ @ScriptVariable private Style currentStyle; /** * The language manager service. */ @OSGiService private LanguageManager languageManager; /** * The relationship manager service. */ @OSGiService private LiveRelationshipManager relationshipManager; /** * The accessibility label. */ @3146596 private String accessibilityLabel; /** * Number indicating how many levels below the navigation root the navigation should start. */ private int structureStart; /** * Number indicating how many levels below the navigation root should be included in the results. * Use "-1" for no limit. */ private int structureDepth; /** * The root page from which to build the navigation. */ private Page navigationRootPage; /** * Placeholder for the list of results. */ private List<NavigationItem> items; /** * Initialize the model. */ @PostConstruct private void initModel() { ValueMap properties = this.resource.getValueMap(); structureDepth = properties.get(PN_STRUCTURE_DEPTH, currentStyle.get(PN_STRUCTURE_DEPTH, -1)); boolean collectAllPages = properties.get(PN_COLLECT_ALL_PAGES, currentStyle.get(PN_COLLECT_ALL_PAGES, true)); if (collectAllPages) { structureDepth = -1; } if (currentStyle.containsKey(PN_STRUCTURE_START) || properties.containsKey(PN_STRUCTURE_START)) { //workaround to maintain the content of Navigation component of users in case they update to the current i.e. the `structureStart` version. structureStart = properties.get(PN_STRUCTURE_START, currentStyle.get(PN_STRUCTURE_START, 1)); } else { boolean skipNavigationRoot = properties.get(PN_SKIP_NAVIGATION_ROOT, currentStyle.get(PN_SKIP_NAVIGATION_ROOT, true)); if (skipNavigationRoot) { structureStart = 1; } else { structureStart = 0; } } } /** * Get the effective navigation root page. * * @2007960 The effective navigation root page. */ private Page getNavigationRoot() { if (this.navigationRootPage == null) { String navigationRootPath = Optional.ofNullable(this.resource.getValueMap().get(PN_NAVIGATION_ROOT, String.class)) .orElseGet(() -> currentStyle.get(PN_NAVIGATION_ROOT, String.class)); this.navigationRootPage = LocalizationUtils.getLocalPage(navigationRootPath, this.currentPage, this.request.getResourceResolver(), this.languageManager, this.relationshipManager) .orElseGet(() -> currentPage.getPageManager().getPage(navigationRootPath)); } return this.navigationRootPage; } @9944223 public List<NavigationItem> getItems() { if (this.items == null) { this.items = Optional.ofNullable(this.getNavigationRoot()) .map(navigationRoot -> getRootItems(navigationRoot, structureStart)) .orElseGet(Stream::empty) .map(item -> this.createNavigationItem(item, getItems(item))) .collect(Collectors.toList()); } return Collections.unmodifiableList(items); } protected NavigationItem newNavigationItem(Page page, boolean active, boolean current, @126844 LinkManager linkManager, int level, List<NavigationItem> children, String parentId, Component component) { return new NavigationItemImpl(page, active, current, linkManager, level, children, parentId, component); } @9944223 @3146596 public String getAccessibilityLabel() { if (this.accessibilityLabel == null) { this.accessibilityLabel = this.resource.getValueMap().get(PN_ACCESSIBILITY_LABEL, String.class); } return this.accessibilityLabel; } @126844 @9944223 public String getExportedType() { return this.resource.getResourceType(); } /** * Builds the navigation tree for a {@code navigationRoot} page. * * @90521 subtreeRoot The page for which to generate the sub-tree. * @2007960 the list of collected navigation trees */ private List<NavigationItem> getItems(@NotNull final Page subtreeRoot) { if (this.structureDepth < 0 || subtreeRoot.getDepth() - this.getNavigationRoot().getDepth() < this.structureDepth) { Iterator<Page> childIterator = subtreeRoot.listChildren(new PageFilter()); return StreamSupport.stream(((Iterable<Page>) () -> childIterator).spliterator(), false) .map(item -> this.createNavigationItem(item, getItems(item))) .collect(Collectors.toList()); } return Collections.emptyList(); } /** * Gets a stream of the top level of pages in the navigation. * * @90521 navigationRoot The navigation root page. * @90521 structureStart The number of levels under the root page to begin collecting pages. * @2007960 Stream of all descendant pages of navigationRoot that are exactly structureStart levels deeper. */ private Stream<Page> getRootItems(@NotNull final Page navigationRoot, final int structureStart) { if (structureStart < 1) { return Stream.of(navigationRoot); } Iterator<Page> childIterator = navigationRoot.listChildren(new PageFilter()); return StreamSupport.stream(((Iterable<Page>) () -> childIterator).spliterator(), false) .flatMap(child -> getRootItems(child, structureStart - 1)); } /** * Create a navigation item for the given page/children. * * @90521 page The page for which to create a navigation item. * @90521 children The child navigation items. * @2007960 The newly created navigation item. */ private NavigationItem createNavigationItem(@NotNull final Page page, @126844 final List<NavigationItem> children) { int level = page.getDepth() - (this.getNavigationRoot().getDepth() + structureStart); boolean current = checkCurrent(page); boolean selected = checkSelected(page, current); return newNavigationItem(page, selected, current, linkManager, level, children, getId(), component); } /** * Checks if the specified page is selected. * A page is selected if it is either: * <ul> * <li>The current page; or,</li> * <li>A page that redirects to the current page; or,</li> * <li>The current page is a child of the specified page</li> * </ul> * * @90521 page The page to check. * @2007960 True if the page is selected, false if not. */ private boolean checkSelected(@NotNull final Page page, boolean current) { return current || this.currentPage.getPath().startsWith(page.getPath() + "/"); } private boolean checkCurrent(@NotNull final Page page) { return this.currentPage.equals(page) || currentPageIsRedirectTarget(page); } /** * Checks if the specified page redirects to the current page. * * @90521 page The page to check. * @2007960 True if the specified page redirects to the current page. */ private boolean currentPageIsRedirectTarget(@NotNull final Page page) { return currentPage.equals(Utils.resolveRedirects(page).getLeft()); } }

My code below

// package com.myproject.core.models.impl; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; import javax.annotation.PostConstruct; import javax.mail.Quota.Resource; import com.adobe.cq.wcm.core.components.internal.Utils; import com.adobe.cq.wcm.core.components.util.AbstractComponentImpl; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.ValueMap; import org.apache.sling.models.annotations.Exporter; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.Via; import org.apache.sling.models.annotations.injectorspecific.OSGiService; import org.apache.sling.models.annotations.injectorspecific.ScriptVariable; import org.apache.sling.models.annotations.injectorspecific.Self; import org.apache.sling.models.annotations.via.ResourceSuperType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.adobe.cq.export.json.ComponentExporter; import com.adobe.cq.export.json.ExporterConstants; import com.adobe.cq.wcm.core.components.internal.LocalizationUtils; import com.adobe.cq.wcm.core.components.commons.link.LinkManager; import com.adobe.cq.wcm.core.components.models.Navigation; import com.adobe.cq.wcm.core.components.models.NavigationItem; import com.day.cq.wcm.api.LanguageManager; import com.day.cq.wcm.api.Page; import com.day.cq.wcm.api.PageFilter; import com.day.cq.wcm.api.components.Component; import com.day.cq.wcm.api.designer.Style; import com.day.cq.wcm.msm.api.LiveRelationshipManager; /** * Navigation model implementation. */ @Model(adaptables = SlingHttpServletRequest.class, adapters = {Navigation.class, ComponentExporter.class}, resourceType = {NavMenuHeaderImpl.RESOURCE_TYPE}) public class NavMenuHeaderImpl implements Navigation { /** * The resource navigation component resource type. */ public static final String RESOURCE_TYPE = "apps/myproject/components/atom_nav-header"; /** * Name of the resource / configuration policy property that defines the accessibility label. */ private static final String PN_ACCESSIBILITY_LABEL = "accessibilityLabel"; /** * The current request. */ @Self private SlingHttpServletRequest request; /** * The link manager. */ @Self private LinkManager linkManager; /** * The current page. */ @ScriptVariable private Page currentPage; /** * The current style. */ @ScriptVariable private Style currentStyle; /** * The language manager service. */ @OSGiService private LanguageManager languageManager; /** * The relationship manager service. */ @OSGiService private LiveRelationshipManager relationshipManager; /** * The accessibility label. */ @3146596 private String accessibilityLabel; /** * Number indicating how many levels below the navigation root the navigation should start. */ private int structureStart; /** * Number indicating how many levels below the navigation root should be included in the results. * Use "-1" for no limit. */ private int structureDepth; /** * The root page from which to build the navigation. */ private Page navigationRootPage; /** * Placeholder for the list of results. */ private List<NavigationItem> items; /** * Initialize the model. */ @PostConstruct private void initModel() { ValueMap properties = this.resource.getValueMap(); structureDepth = properties.get(PN_STRUCTURE_DEPTH, currentStyle.get(PN_STRUCTURE_DEPTH, -1)); boolean collectAllPages = properties.get(PN_COLLECT_ALL_PAGES, currentStyle.get(PN_COLLECT_ALL_PAGES, true)); if (collectAllPages) { structureDepth = -1; } if (currentStyle.containsKey(PN_STRUCTURE_START) || properties.containsKey(PN_STRUCTURE_START)) { //workaround to maintain the content of Navigation component of users in case they update to the current i.e. the `structureStart` version. structureStart = properties.get(PN_STRUCTURE_START, currentStyle.get(PN_STRUCTURE_START, 1)); } else { boolean skipNavigationRoot = properties.get(PN_SKIP_NAVIGATION_ROOT, currentStyle.get(PN_SKIP_NAVIGATION_ROOT, true)); if (skipNavigationRoot) { structureStart = 1; } else { structureStart = 0; } } } /** * Get the effective navigation root page. * * @2007960 The effective navigation root page. */ private Page getNavigationRoot() { if (this.navigationRootPage == null) { String navigationRootPath = Optional.ofNullable(this.resource.getValueMap().get(PN_NAVIGATION_ROOT, String.class)) .orElseGet(() -> currentStyle.get(PN_NAVIGATION_ROOT, String.class)); this.navigationRootPage = LocalizationUtils.getLocalPage(navigationRootPath, this.currentPage, this.request.getResourceResolver(), this.languageManager, this.relationshipManager) .orElseGet(() -> currentPage.getPageManager().getPage(navigationRootPath)); } return this.navigationRootPage; } @9944223 public List<NavigationItem> getItems() { if (this.items == null) { this.items = Optional.ofNullable(this.getNavigationRoot()) .map(navigationRoot -> getRootItems(navigationRoot, structureStart)) .orElseGet(Stream::empty) .map(item -> this.createNavigationItem(item, getItems(item))) .collect(Collectors.toList()); } return Collections.unmodifiableList(items); } protected NavigationItem newNavigationItem(Page page, boolean active, boolean current, @126844 LinkManager linkManager, int level, List<NavigationItem> children, String parentId, Component component) { return new NavigationItemImpl(page, active, current, linkManager, level, children, parentId, component); } @9944223 @3146596 public String getAccessibilityLabel() { if (this.accessibilityLabel == null) { this.accessibilityLabel = this.resource.getValueMap().get(PN_ACCESSIBILITY_LABEL, String.class); } return this.accessibilityLabel; } @126844 @9944223 public String getExportedType() { return this.resource.getResourceType(); } /** * Builds the navigation tree for a {@code navigationRoot} page. * * @90521 subtreeRoot The page for which to generate the sub-tree. * @2007960 the list of collected navigation trees */ private List<NavigationItem> getItems(@NotNull final Page subtreeRoot) { if (this.structureDepth < 0 || subtreeRoot.getDepth() - this.getNavigationRoot().getDepth() < this.structureDepth) { Iterator<Page> childIterator = subtreeRoot.listChildren(new PageFilter()); return StreamSupport.stream(((Iterable<Page>) () -> childIterator).spliterator(), false) .map(item -> this.createNavigationItem(item, getItems(item))) .collect(Collectors.toList()); } return Collections.emptyList(); } /** * Gets a stream of the top level of pages in the navigation. * * @90521 navigationRoot The navigation root page. * @90521 structureStart The number of levels under the root page to begin collecting pages. * @2007960 Stream of all descendant pages of navigationRoot that are exactly structureStart levels deeper. */ private Stream<Page> getRootItems(@NotNull final Page navigationRoot, final int structureStart) { if (structureStart < 1) { return Stream.of(navigationRoot); } Iterator<Page> childIterator = navigationRoot.listChildren(new PageFilter()); return StreamSupport.stream(((Iterable<Page>) () -> childIterator).spliterator(), false) .flatMap(child -> getRootItems(child, structureStart - 1)); } /** * Create a navigation item for the given page/children. * * @90521 page The page for which to create a navigation item. * @90521 children The child navigation items. * @2007960 The newly created navigation item. */ private NavigationItem createNavigationItem(@NotNull final Page page, @126844 final List<NavigationItem> children) { int level = page.getDepth() - (this.getNavigationRoot().getDepth() + structureStart); boolean current = checkCurrent(page); boolean selected = checkSelected(page, current); return newNavigationItem(page, selected, current, linkManager, level, children, getId(), component); } /** * Checks if the specified page is selected. * A page is selected if it is either: * <ul> * <li>The current page; or,</li> * <li>A page that redirects to the current page; or,</li> * <li>The current page is a child of the specified page</li> * </ul> * * @90521 page The page to check. * @2007960 True if the page is selected, false if not. */ private boolean checkSelected(@NotNull final Page page, boolean current) { return current || this.currentPage.getPath().startsWith(page.getPath() + "/"); } private boolean checkCurrent(@NotNull final Page page) { return this.currentPage.equals(page) || currentPageIsRedirectTarget(page); } /** * Checks if the specified page redirects to the current page. * * @90521 page The page to check. * @2007960 True if the specified page redirects to the current page. */ private boolean currentPageIsRedirectTarget(@NotNull final Page page) { return currentPage.equals(Utils.resolveRedirects(page).getLeft()); } }

 

BrianKasingli
Community Advisor and Adobe Champion
Community Advisor and Adobe Champion
July 12, 2023

I don't see a problem with your code... make sure you are using the correct AEM Cloud SDK (if you are on AEMaaCS), and if you are using classic AEM, make sure you have the correct service pack and/or the AEM WCM Core Components installed as expected.

 

This code works fine for me.

<nav data-sly-use.navigation="com.adobe.cq.wcm.core.components.models.Navigation" data-sly-use.template="core/wcm/components/commons/v1/templates.html" data-sly-use.groupTemplate="group.html" data-sly-call="${groupTemplate.group @ items=navigation.items}" data-sly-test.hasContent="${navigation.items.size > 0}" id="${navigation.id}" class="cmp-navigation" itemscope itemtype="http://schema.org/SiteNavigationElement" data-cmp-data-layer="${navigation.data.json}" aria-label="${navigation.accessibilityLabel}"> </nav> <sly data-sly-call="${template.placeholder @ isEmpty=!hasContent, classAppend='cmp-navigation'}"></sly>