All About Custom Lightning Page Templates

Have you ever wished for a new layout for your home page? How about more control over the columns on your record page? With the custom Lightning page template feature and a little bit of code, you can go way beyond the out of the box templates. This blog post is going to help you get started with your own templates and then we will dive into some cool things you can do!

What is a Lightning page template anyway?

Lightning page templates are components that define a page’s regions and can be used for Home, Record or App pages. Both standard and custom templates appear in the App Builder’s New Page Wizard and can be used to create new pages for an app. They are pretty easy to create, so let’s dive in!

Getting started

There are a few things you need to be aware of when building a new Lightning page template. The most important thing is to decide where you want your template to be used. You must specify if you want it available on an App, Home or Record page. You have to pick only one, since you can’t use more than one interface.

The next thing to be aware of the .svg file, which is an image type. This file works differently for Lightning page templates than Lightning components. For a component, an .svg would show up in the left-hand bar of the Lightning App Builder. For a Lightning page template, it shows up on the screen where you select which template you want to use. No matter what you do, your custom templates will appear in the new page wizard, but if you leave the .svg alone, it will be hard to distinguish your templates from each other. You can add an .svg file to provide App Builder users with an image preview of the template.


The black box here identifies where the .svg will appear.

Exactly what your users asked for: A Home Page with three regions

We’ve just received a request for an amazing custom Lightning page template in our org. Our first step is to dream about what kind of page we would like. Let’s imagine that your users have requested a Home page with three columns. It’s a pretty standard ask with a simple look and feel, but you draw it up anyway, just to be sure.

Next, we are going to create a brand new Lightning component. So we can remember, we’ve called it ThreeRegionHome (so creative, right?). We’ve got to make sure we implement the right interface for a Home page and we add a description, because we are great developers. Since we know we only need three regions and they are going to be columns, we create some attributes for those. So far our component looks like this:

ThreeRegionHome.cmp

<aura:component implements="lightning:homeTemplate" 
                description="A home page you always dreamed of, 3 columns." >
    <aura:attribute name="column1" type="Aura.Component[]" />
    <aura:attribute name="column2" type="Aura.Component[]" />
    <aura:attribute name="column3" type="Aura.Component[]" />
</aura:component>

It is pretty simple but it doesn’t do anything yet — it won’t even show up in the Lightning App Builder! Oh no! Thankfully the fix is pretty easy — we just have to write our design file. The label in our design file is the label that will show up in the Lightning App Builder, so we make sure it is something you and your admins will understand.

ThreeRegionHome.design

<design:component label="3 Column Page">
    <flexipage:template >
      <flexipage:region name="column1" defaultWidth="Medium" />
      <flexipage:region name="column2" defaultWidth="Medium" />
      <flexipage:region name="column3" defaultWidth="Medium" />
  </flexipage:template>
</design:component>

Now our page shows up in Lightning App Builder, but we don’t see any place to add components to our columns. This is because all we’ve done so far is say there will be attributes, but we haven’t told the page what it should look like. This is when we start leveraging lightning:layout and lightning:layoutItem.

ThreeRegionHome.cmp

<aura:component implements="lightning:homeTemplate" 
                description="A home page you always dreamed of, 3 columns." >
    <aura:attribute name="column1" type="Aura.Component[]" />
    <aura:attribute name="column2" type="Aura.Component[]" />
    <aura:attribute name="column3" type="Aura.Component[]" />
    
    <div>
        <lightning:layout horizontalAlign="spread" pullToBoundary="small">
            <lightning:layoutItem size="4" flexibility="grow" 
                                  padding="around-small">
                {!v.column1}
            </lightning:layoutItem>
            <lightning:layoutItem size="4" flexibility="grow" 
                                  padding="around-small">         
                {!v.column2}
            </lightning:layoutItem>
            <lightning:layoutItem size="4" flexibility="grow" 
                                  padding="around-small">
                {!v.column3}
            </lightning:layoutItem>
        </lightning:layout>
    </div> 
</aura:component>

We can keep working on this page by doing a few other custom things, the most important of which is creating the .svg file. You can create an .svg for your page with tools like Photoshop, Sketch or any other design creation tool. Once we’ve created that .svg file and added it as ThreeRegionHome.svg we have completed the template.

Now you can use it in action! In Lightning App Builder we can create a new home page (or edit an old home page) and have it leverage our fancy new template.

Making a Record page with collapsing regions

Our users have fallen in love with the new home page and already have brilliant ideas about other kinds of record pages that they would love.

Picture this scenario: You set up a whiteboarding session and everyone agreed on a brand new design. It’s a simple page, but it will allow users to collapse and expand an area on the right side of a record page.


This is the new svg your users defined.

Just like before, you start with your amazing component file and you dive right into the nitty gritty. But WHOA, your users requested that some regions collapse, and you’ve never done that before!

Let’s take a quick look at the component code to do this.

<aura:component implements="lightning:recordHomeTemplate" description="Full-width header above a main column and collapsible right sidebar.">

    <aura:attribute name="header" type="Aura.Component[]" description="Header region"/>
    <aura:attribute name="main" type="Aura.Component[]" description="Main region"/>
    <aura:attribute name="sidebar" type="Aura.Component[]" description="Collapsible sidebar region"/>

    <aura:attribute name="isSidebarCollapsed" type="Boolean" access="PRIVATE" default="false" />

    <div>
        <div>{!v.header}</div>
        <lightning:layout class="slds-m-top_medium">
            <lightning:layoutItem flexibility="auto">
                {!v.main}
            </lightning:layoutItem>
            <lightning:layoutItem flexibility="no-flex">
                <lightning:buttonIcon onclick ="{!c.toggleSection}"
                                      class="design-allow-interaction toggle slds-p-around_xxx-small slds-m-horizontal_xx-small"
                                      variant="border-filled"
                                      iconName="{! v.isSidebarCollapsed ? 'utility:chevronleft' : 'utility:chevronright' }" 
                                      alternativeText="{! v.isSidebarCollapsed ? 'Expand Sidebar' : 'Collapse Sidebar' }" />
            </lightning:layoutItem>
            <lightning:layoutItem class="{! v.isSidebarCollapsed ? ' slds-hide' : '' }" size="4">
                {!v.sidebar}
            </lightning:layoutItem>
        </lightning:layout>
    </div>
</aura:component>

However, it won’t work until we write a simple Javascript method to toggle what is open. It turns out to be pretty simple!

({
    toggleSection : function(component, event, helper) {
        component.set('v.isSidebarCollapsed', !component.get('v.isSidebarCollapsed'));
    }
})

Of course, we can’t forget our design file. You’ll notice that we decided to make our columns and the left and right smaller than the middle column.

<design:component label="Header and Collapsible Right Sidebar">
    <flexipage:template>
        <flexipage:region name="header" defaultWidth="LARGE" />
        <flexipage:region name="main" defaultWidth="MEDIUM" />
        <flexipage:region name="sidebar" defaultWidth="SMALL" />
    </flexipage:template>
</design:component>

Finally, we add our custom .svg and it’s off to the races to update our record pages to our new layout!

<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" viewBox="0 0 565 153" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Full-width header above a main column and collapsible right sidebar.</title>
<desc>Created with Sketch.</desc>
<defs>
<path id="d" d="m52.919 23.328c1.0531 1.6487 7.4332 2.9429 7.4332 2.9429s1.6838 1.2352-4.5419 1.2352c-4.383-1.2e-6 -17.873-7e-7 -25.475-3e-7 -7.6019-4e-7 -21.092-9e-7 -25.475 3e-7 -6.2257 2.5e-6 -4.5419-1.2352-4.5419-1.2352s6.3801-1.2942 7.4332-2.9429c1.0531-1.6487 2.8854-23.259 2.8854-23.259h39.397s1.8324 21.61 2.8854 23.259z"/>
<rect id="b" y=".48418" width="200" height="123.57" rx="3.8554"/>
<path id="c" d="m52.919 23.328c1.0531 1.6487 7.4332 2.9429 7.4332 2.9429s1.6838 1.2352-4.5419 1.2352c-4.383-1.2e-6 -17.873-7e-7 -25.475-3e-7 -7.6019-4e-7 -21.092-9e-7 -25.475 3e-7 -6.2257 2.5e-6 -4.5419-1.2352-4.5419-1.2352s6.3801-1.2942 7.4332-2.9429c1.0531-1.6487 2.8854-23.259 2.8854-23.259h39.397s1.8324 21.61 2.8854 23.259z"/>
<rect id="a" y=".48418" width="200" height="123.57" rx="3.8554"/>
</defs>
<g fill="none" fill-rule="evenodd">
<g transform="translate(-1 -64)">
<g transform="translate(58 63)">
<g transform="translate(69.6 124.02)">
<path d="m60.555 26.901v0.77015c0.064783 0.36534-0.49884 0.94111-4.749 0.94111-4.3826-1.2e-6 -17.872-7e-7 -25.473-3e-7 -7.6013-4e-7 -21.091-9e-7 -25.473 3e-7 -4.2501 1.7e-6 -4.8138-0.57576-4.7436-0.94111l-0.005392-0.77015 0.75324 0.33579h58.938l0.75324-0.33579z" opacity=".5"/>
<path d="m60.555 26.565v0.77015c0.064783 0.36534-0.49884 0.94111-4.749 0.94111-4.3826-1.3e-6 -17.872-8e-7 -25.473-4e-7 -7.6013-4e-7 -21.091-9e-7 -25.473 4e-7 -4.2501 1.6e-6 -4.8138-0.57576-4.7436-0.94111l-0.005392-0.77015 0.75324 0.33579h58.938l0.75324-0.33579z" fill="#C6C7CA"/>
<mask fill="white">
<use xlink:href="#d"/>
</mask>
<use fill="#D8D8D8" xlink:href="#d"/>
</g>
<g transform="translate(0 .48418)">
<mask id="f" fill="white">
<use xlink:href="#b"/>
</mask>
<use fill="#9B9B9B" fill-opacity=".30016" xlink:href="#b"/>
<use fill="#E1E1E1" xlink:href="#b"/>
<g fill="#fff" mask="url(#f)">
<g transform="translate(6.747 9.1994)">
<rect width="186.54" height="104.25"/>
</g>
</g>
</g>
<g transform="translate(6.9156 9.3421)">
<rect y=".32109" width="186.35" height="20.132" fill="#54698D"/>
<rect x="4.8193" y="24.963" width="130.36" height="74.024" fill="#54698D"/>
<rect x="140.56" y="24.963" width="40.562" height="74.024" fill="#54698D"/>
<rect x="135" y="25" width="8" height="74.024" fill="#9FAAB5"/>
</g>
<g transform="translate(249)">
<g transform="translate(69.6 124.02)">
<path d="m60.555 26.901v0.77015c0.064783 0.36534-0.49884 0.94111-4.749 0.94111-4.3826-1.2e-6 -17.872-7e-7 -25.473-3e-7 -7.6013-4e-7 -21.091-9e-7 -25.473 3e-7 -4.2501 1.7e-6 -4.8138-0.57576-4.7436-0.94111l-0.005392-0.77015 0.75324 0.33579h58.938l0.75324-0.33579z" opacity=".5"/>
<path d="m60.555 26.565v0.77015c0.064783 0.36534-0.49884 0.94111-4.749 0.94111-4.3826-1.3e-6 -17.872-8e-7 -25.473-4e-7 -7.6013-4e-7 -21.091-9e-7 -25.473 4e-7 -4.2501 1.6e-6 -4.8138-0.57576-4.7436-0.94111l-0.005392-0.77015 0.75324 0.33579h58.938l0.75324-0.33579z" fill="#C6C7CA"/>
<mask fill="white">
<use xlink:href="#c"/>
</mask>
<use fill="#D8D8D8" xlink:href="#c"/>
</g>
<g transform="translate(0 .48418)">
<mask id="e" fill="white">
<use xlink:href="#a"/>
</mask>
<use fill="#9B9B9B" fill-opacity=".30016" xlink:href="#a"/>
<use fill="#E1E1E1" xlink:href="#a"/>
<g fill="#fff" mask="url(#e)">
<g transform="translate(6.747 9.1994)">
<rect width="186.54" height="104.25"/>
</g>
</g>
</g>
<g transform="translate(6.9156 9.3421)">
<rect y=".32109" width="186.35" height="20.132" fill="#54698D"/>
<rect x="4.8193" y="24.963" width="175.18" height="74.024" fill="#54698D"/>
<g transform="translate(178.28 24.998)">
<rect x=".084426" y="-2.8422e-14" width="8" height="74.024" fill="#9FAAB5"/>
<path transform="translate(3.5 38.014) rotate(180) translate(-3.5 -38.014)" d="m5.1056 38.461l-3.382 1.691c-0.24699 0.12349-0.54733 0.023382-0.67082-0.22361-0.034714-0.069428-0.052786-0.14598-0.052786-0.22361v-3.382c0-0.27614 0.22386-0.5 0.5-0.5 0.077623 0 0.15418 0.018073 0.22361 0.052786l3.382 1.691c0.24699 0.12349 0.3471 0.42383 0.22361 0.67082-0.048382 0.096764-0.12684 0.17522-0.22361 0.22361z" fill="#fff"/>
</g>
</g>
</g>
</g>
<path d="m205.52 135.8l-3.382 1.691c-0.24699 0.12349-0.54733 0.023382-0.67082-0.22361-0.034714-0.069428-0.052787-0.14598-0.052787-0.22361v-3.382c0-0.27614 0.22386-0.5 0.5-0.5 0.077623 0 0.15418 0.018073 0.22361 0.052787l3.382 1.691c0.24699 0.12349 0.3471 0.42383 0.22361 0.67082-0.048382 0.096764-0.12684 0.17522-0.22361 0.22361z" fill="#fff"/>
</g>
</g>
</svg>

Pulling it all together

Now that you’ve seen a few really snazzy ways to make a Custom Lightning Page Template, you can check out even more examples on Github or download them into your own org through the Salesforce App Exchange. We also encourage everyone to dive in and make your own! Share your custom template with us on Twitter and tell us about your amazing use cases.

Heather Dykstra
Developer Evangelist, Salesforce
@SlytherinChika

Additional resources

Published
August 14, 2018
Topics: