Core Component Breadcrumb Title

Avatar

Avatar
Affirm 5
Level 3
jetate
Level 3

Likes

12 likes

Total Posts

69 posts

Correct reply

5 solutions
Top badges earned
Affirm 5
Validate 10
Validate 1
Ignite 3
Ignite 1
View profile

Avatar
Affirm 5
Level 3
jetate
Level 3

Likes

12 likes

Total Posts

69 posts

Correct reply

5 solutions
Top badges earned
Affirm 5
Validate 10
Validate 1
Ignite 3
Ignite 1
View profile
jetate
Level 3

15-06-2020

Is it possible to override the Breadcrumb or Page List component to use a different page title than the Navigation Title? 

 

I have a requirement where I need to use a shorter title in the Breadcrumb component than in the Page List Component, however, both are using the Navigation Title. If there is a way that I can use one title type for one component and another for the other component, that would be ideal.

 

I'm a relative beginner with Java and don't entirely understand how the Delegation Pattern for Sling Models (https://github.com/adobe/aem-core-wcm-components/wiki/Delegation-Pattern-for-Sling-Models) could tie into what I'm trying to do here, but if there is a tutorial or some information that might help guide a solution, I would appreciate the insight.

Accepted Solutions (1)

Accepted Solutions (1)

Avatar

Avatar
Validate 1
MVP
Theo_Pendle
MVP

Likes

238 likes

Total Posts

251 posts

Correct reply

105 solutions
Top badges earned
Validate 1
Ignite 5
Ignite 3
Ignite 10
Ignite 1
View profile

Avatar
Validate 1
MVP
Theo_Pendle
MVP

Likes

238 likes

Total Posts

251 posts

Correct reply

105 solutions
Top badges earned
Validate 1
Ignite 5
Ignite 3
Ignite 10
Ignite 1
View profile
Theo_Pendle
MVP

15-06-2020

Hi @jetate,

It depends what you mean by "one title type for one component and another for the other component", because there are many title types. However, let's have a look at why the Navigation Title is used.

The breadcrumb model returns a list of NavigationItems (the interface). These are in fact instances of BreadcrumbItemImpl (the class). They in turn fetch the title property (which is used in the rednering HTL script using the following algorithm:

@Override
    public String getTitle() {
        String title = page.getNavigationTitle();
        if (title == null) {
            title = page.getPageTitle();
        }
        if (title == null) {
            title = page.getTitle();
        }
        if (title == null) {
            title = page.getName();
        }
        return title;
    }

 So all you need to do is override this behavior slightly. Let's say for example that you want to use the Page Title and not the Navigation Title in a breadcrumb, you should create the following item:

import com.adobe.cq.wcm.core.components.models.NavigationItem;
import lombok.Getter;
import lombok.experimental.Delegate;

public class CustomNavigationItem implements NavigationItem {

    // Here we delegate everything to the original item, except the getTitle method (see interface below)
    @Delegate(excludes = DelegationExclusion.class)
    private final NavigationItem delegate;

    // Rather than getting a title from a page using an the algorithm I showed above, this item will simply return
    // whatever String was given to it in its constructor
    @Getter
    private final String title;

    public CustomNavigationItem(final NavigationItem item, final String title) {
        this.delegate = item;
        this.title = title;
    }

    private interface DelegationExclusion {
        String getTitle();
    }
}

Then, return these CustomNavigationItems rather than the default items using this model:

import com.adobe.cq.wcm.core.components.models.Breadcrumb;
import com.adobe.cq.wcm.core.components.models.NavigationItem;
import com.day.cq.wcm.api.PageManager;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.Via;
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 java.util.Collection;
import java.util.stream.Collectors;

@Model(
        adaptables = {Resource.class, SlingHttpServletRequest.class},
        adapters = Breadcrumb.class,
        resourceType = "demo/components/content/breadcrumb",
        defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)
public class CustomBreadcrumb implements Breadcrumb {

    @Self
    @Via(type = ResourceSuperType.class)
    private Breadcrumb delegate;

    @ScriptVariable
    private PageManager pageManager;

    @Override
    public Collection<NavigationItem> getItems() {

        // For each item, create an instance of our custom item
        return delegate.getItems().stream().map(item -> {

            // Set the title to be the page title
            final String pageTitle = pageManager.getPage(item.getPath()).getPageTitle();
            return new CustomNavigationItem(item, pageTitle);
            
        }).collect(Collectors.toList());
    }

    @Override
    public String getExportedType() {
        return delegate.getExportedType();
    }
}

Here is the result! The page properties:

Selection_168.png

Ans as you can see, the page title is used, not the navigation title! Sorry, didn't have time for CSS 😛 

Selection_169.png

I've been generous with comments on the parts that are relative to your use-case. If you want a step-by-step tutorial to explain exactly how it all works, I wrote one recently here: https://levelup.gitconnected.com/aem-extend-core-component-models-using-resource-type-association-an... 🙂

Answers (0)