8

I am creating my first lightning application and am using the LDS UI framework. I have created a header component with a navigation bar, and embedded this component in my Lightning app.

<aura:application extends="force:slds">
  <c:Header />
  <c:Footer />
</aura:application>

What I would like to do is have the navbar (which is inside the header) link to other pages in the app, while using the same header and footer - only the body would change. Is there lightning functionality that accomplishes this? Or would I have to create another application to link to? If this is not normal architecture for a lightning app, please let me know as well. I would rather not use VisualForce too.

2 Answers 2

5

You are probably going to want to use "events" to do this.

The approach I would consider comprises the following:

1) A Navigation component with links/buttons that fire a lightning event (this is your header)

2) The Lightning Event (a separate component - this is new to your setup)

3) A "body" component (could be one, or many) that listens for the events and changes its content dynamically (even dynamically loading other components) (this is probably your footer)

So (1) will be a component with some HTML markup including a navigation item like:

<li><a href="#" onclick="{!c.activitySelected}">Activity</a></li>

And in the component controller a method that [calls a helper method that] does:

    performActivitySelected : function() {
        var navSelected= $A.get("e.c:navSelected");
        navSelected.setParams({ "name" : "activity" });
        navSelected.fire();
    },

The navSelected var in that then references (2) which is this Lightning event (note: the name of the event component has to line up with the $A.get from above)

<aura:event type="APPLICATION" description="Event from nav">
<aura:attribute name="name" type="String"/>
</aura:event>

and then finally, in the "main" body / footer component (3) you want some markup in the component to listen to these events and change the "body" area like:

<aura:component >
    <aura:handler event="c:navSelected" action="{!c.onMenuItemSelected}"/>
    <div aura:id="displayPort"></div>
</aura:component>

In the controller then (and use the helpers appropriately to delegate this lark) use:

onMenuItemSelected : function(component, name) {
        $A.createComponent(
            "c:" + name,
            [],
            function(newComponent, status, statusDetail) {
                var content = component.find("displayPort");
                content.set("v.body", newComponent);
            }
        );
}

so when the component hears the Event being fired, it loads a component - in this case - with the given name and shoves it into it's body - but you can do anything you like from that point.

2
  • Thanks for this, should definitely help me out a lot. I do think that Lightning apps are best suited for one page, multiple component apps (at least for right now), but I have some use cases where multiple pages make sense in regards to UI and separation of responsibilities.
    – col_powers
    Jan 5, 2017 at 15:43
  • yeah... I'm not sure why I started with that comment :D I might edit it out... I must have started writing that answer just as my coffee ran out. Hope it does help, good luck! Jan 5, 2017 at 15:45
3

You could try using the inheritance concept in Lightning component instead of creating separate components for header and footer and adding it where ever you need.

Since you are already extending your app with force:slds and a Lightning App/Component is extensible only once. You need to have a Base App which extends force:slds, which in turn can be used to extend your other apps. Restriction on extending app/component t's mentioned here

Now, make your Base App extendable by adding extensible=true in the root tag, which contains the header and footer markups. App's extending the Base App, will have header and footer automatically inherited to your App.

More info about inheritance in Lightning Component can be found here.

baseApp.app:

<aura:application extensible="true" extends="force:slds">
    <aura:attribute name="header" type="String" default="Default Header" access="public"/>
    <aura:attribute name="footer" type="String" default="Default Footer" access="public"/>

    <div>
    {!v.header}
    </div>

    <div>
    {!v.body}
    </div>

    <div>
    {!v.footer}    
    </div>
</aura:application>

myApp.app:

<aura:application extends="c:baseApp">
    <!-- use aura:set to override the default value -->
    <aura:set attribute="header" value="My header" /> 
    <aura:set attribute="foolter" value="My footer" />
     My Actual Body
</aura:application>

Above principle can be applied to components too.

Finally, regarding navigation you need to refresh the page by changing the browser url for App navigation. If you are planning to setup component navigation then, you can use @SimonLawerence's approach.

Few answer's on component navigation also follow same approach too:

  1. How to set up views and navigation in Lightning's Answer
  2. How to navigate from one lightning component to another lightning component's Answer
2
  • I also like this approach, although it does involve creating multiple .app files. I will have to think more about the architecture of my app and how best to divide responsibilities between pages or apps. Thanks for the suggestion.
    – col_powers
    Jan 5, 2017 at 18:44
  • @col_powers Ya I agree with the need of multiple base app files, if the your header and footer are entirely different across apps. Honestly, I know this won't help you entirely, just wanted to share a pattern I used in recent project which dealt with somewhat similar thing you are looking for.
    – Praveen
    Jan 6, 2017 at 10:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .