Saturday, 15 December 2012

Building a Templated Web Site with Force.com - Part 4

In Part 1 of this series, I looked at how to turn an HTML page into a Visualforce page in order to use it as a template for a Force.com site. Part 2 covered how to turn the page into a template and create a home page that used the template to provide the common content.  Part 3 explained how to expose the pages to the world via an unauthenticated Force.com site.

Thus far I've focused on a single page, but the site has a number of tabs that are supplied by default in the template - Blogs, Photos, About, Links and Contacts.  For the purposes of this blog post, I'm going to create two additional pages - About and Contacts.

As I already have a home page that uses the template, I've cloned this to create new visualforce pages named 'about' and 'contact'.  These contain minimal content.

The contact page:

Screen Shot 2012 12 15 at 11 53 30

and the about page:

Screen Shot 2012 12 15 at 11 53 44

Next I need to create a way to navigate to the pages.  While the tabs contain links, these are empty anchor tags, as can be seen from the template markup:

<div id="menu">
	<ul>
		<li class="current_page_item"><a href="#">Homepage</a></li>
		<li><a href="#">Blog</a></li>
		<li><a href="#">Photos</a></li>
		<li><a href="#">About</a></li>
		<li><a href="#">Links</a></li>
		<li><a href="#">Contact</a></li>
	</ul>
</div>

Changing the links to point to my Visualforce pages might seem as simple as replacing the '#' with the Visualforce page link.  Unfortunately, Force.com sites need the page to be specified as '/contact', while if the pages are accessed from the Salesforce UI it needs to be specified as '/apex/contact'.  For this reason, its best practice to use the $Page global variable - this will generate the appropriate link based on the user's context.  As I've created pages for the Homepage, About and Contact tabs, the new markup is:

<div id="menu">
	<ul>
		<li class="current_page_item"><a href="{!$Page.Home}">Homepage</a></li>
		<li><a href="#">Blog</a></li>
		<li><a href="#">Photos</a></li>
		<li><a href="{!$Page.about}">About</a></li>
		<li><a href="#">Links</a></li>
		<li><a href="{!$Page.Contact}">Contact</a></li>
	</ul>
</div>

The links now work correctly, but the Homepage tab is always the one highlighted due to the class="current_page_item" attribute. This markup exists in the template, so I need find a way to identify the actual page and set the attribute on the appropriate tab.  

I could write a Visualforce controller for the page, but I'm trying to avoid that at this point and build the site entirely in Visualforce.  I could also add some markup to determine the name of the current URL, and highlight the tab that matches.  The downside to that is if I change the purpose of a page, I have to update the template.  Ideally I'd like to define the tab that should be highlighted in the underlying page, and make the template responsible for the rendering only.

The way that I've handed this is to set the tab name into a variable using the <apex:variable/> component, and then conditionally render the class name based on this variable.

In the underlying pages, its simply another define component - here's the markup from the about page:

<apex:define name="tabdef">
	<apex:variable var="tab" value="about"/>
</apex:define>

there's a little more to do in the template page - I have to define an initial value for the 'tab' variable, otherwise I can't use it elsewhere in the page - I've defaulted to the Homepage tab - that way if I have pages that don't belong to a particular tab, the leftmost will be highlighted.  Then I have to include the value from the underlying page (if this isn't present the default will be used) and finally check the value of tab variable when rendering each tab element.

<div id="menu">
	<apex:variable var="tab" value="home" />
	<apex:insert name="tabdef" />
	<ul>
		<li class="{!IF(tab=='home', 'current_page_item', '')}"><a href="{!$Page.Home}">Homepage</a></li>
		<li><a href="#">Blog</a></li>
		<li><a href="#">Photos</a></li>
		<li class="{!IF(tab=='about', 'current_page_item', '')}"><a href="{!$Page.about}">About</a></li>
		<li><a href="#">Links</a></li>
		<li class="{!IF(tab=='contact', 'current_page_item', '')}"><a href="{!$Page.Contact}">Contact</a></li>
	</ul>
</div>

Looking at my contact page, now, the correct tab is highlighted:

Screen Shot 2012 12 15 at 12 30 49

All that remains is to add the new Visualforce pages to my Force.com site.  On the site setup page (Setup -> App Setup -> Develop -> Sites and click through the site label), select the Edit button on the Site Visualforce Pages section:

Screen Shot 2012 12 15 at 12 32 50

and then add the new pages via the dialog and click the 'Save' button:

Screen Shot 2012 12 15 at 12 36 49

Navigating to the about page via the site's custom URL, shows that all of my new functionality has been made available to the site:

 

Screen Shot 2012 12 15 at 12 38 05

The template, pages and static resources are available in the Part4 directory of the github repository for this blog series at:

https://github.com/keirbowden/blog_force_com_sites

This post is probably the final one in this series, unless another topic occurs to me or is suggested in the comments.

 

1 comment: