I ran into a problem creating the navigation for the footer rendering on a page – On there I needed to have links to the following pages: terms, contact, careers, and the sitemap. The problem arose when trying to add ‘Contact’ and ‘Careers’: ‘Contact’ was a few levels down in the tree of content items and ‘Careers’ was an external page. Initially, I had a checkbox in the template of each page for if the item was in the footer (ie: InFooterNav checked) and then the XSLT file would go through the entire list of items to find what would be in the footer navigation. It wasn’t an ideal solution when so few items had the tag in the entire site and it did not help with my external link at all. Thus was born: The Link Template!
The new template basically consisted of:
Link Data:
- Link: General Link //This is the link to our item or the URL for the external page
- Nav Title: Single Line Text //The title we want to have displayed in our menu – this is the same as in my regular items
- Target: Single Line Text (or a drop down list) //The target if we want to open the page in a new window – **this can be skipped since general link has this option
Properties:
- InFooterNav: Checkbox //Just a checkbox to see if this link is going to be in our footer, this is the same as regular items.
Within the Standard Values I assigned a new layout for the items with the following code within:
<% Sitecore.Data.Items.Item item = Sitecore.Context.Item;
Response.Redirect(((Sitecore.Data.Fields.LinkField)item.Fields["Link"]).Url); %>
The above redirects the user to whatever URL was provided within the “Link” field.
I then created a bunch of items with the appropriate links in the folder where other footer only type items also lived – for our example let us say “/sitecore/content/Home/Footer/”
To retrieve my footer items I now only had to check that folder and not search the entire site to actually see if the box is checked.
And a little more useful - using this template, I could put a link to any external page under any item – allowing me to have external links within my navigation such as Careers.
The above layout will work fine for my footer, but what if you wanted links to open in other windows? Or didn’t want to take the extra step of creating a layout? The rendering can be changed to make use of our new template:
<ul>
<xsl:for-each select="$home/Footer/item[sc:fld('InFooterNav',.) = '1']">
<li>
<xsl:choose>
<xsl:when test="@template = 'link template'">
<xsl:variable name="linkTarget" select="sc:fld('Target',.)" />
<sc:link field="Link" target="{$linkTarget}" >
<sc:text field="Nav Title" />
</sc:link>
</xsl:when>
<xsl:otherwise>
<sc:link>
<sc:text field="Nav Title" />
</sc:link>
</xsl:otherwise>
</xsl:choose>
</li>
</xsl:for-each>
</ul>
Above we have a choose statement to determine if this is using the new link template or not (called “Link Template” but listed in lowercase):
<xsl:when test="@template = 'link template'">
Then we create a variable for our target and create the link based on our General Link field called “Link” by specifying it for field:
<xsl:variable name="linkTarget" select="sc:fld('Target',.)" />
<sc:link field="Link" target="{$linkTarget}" >
<sc:text field="Nav Title" />
</sc:link>
Otherwise if it is a normal item in the tree, we give it a normal link and continue to the next item!
<xsl:otherwise>
<sc:link>
<sc:text field="Nav Title" />
</sc:link>
</xsl:otherwise>
** General Links can specify the target for you so a lot of the above isn’t necessary as long as you’re using sc:link!
Good job, Amy, very interesting post and clear explanation.
ReplyDeleteA few things which have been appeared in my "fault-finding" brain:) :
1) There is possible Null reference exception in code line "item.Fields["Link"]).Url" because the item may not contain field "Link" for some reason. So you will try to get "Url" property from null. There should be checking for not null value first.
2) Actually, redirecting to the link got from Url property of LinkField is not a good idea if you would like to have universal feature because of additional parameters which should be assigned to link (in example query string which stores in LinkField), also redirect depends from type of link. In example if there is internal link stored in that field - I suppose you can't make correct redirect just using URL property. So, there should be more complex and smart method which recognizes the kind of link and do appropriate actions for building correct link url (using LinkManager.GetItemUrl() or MediaManager.GetMediaUrl or finally Url property).
Of course, I should say - that these remarks can be useful for creating some working "universal":) redirector and are not suitable well for the code in this post which has been made as simple and very understandable example:)
Hi Ivan,
ReplyDeleteThank you for your comment! I'm going to add a more 'universal' redirector to my to-do list (and checking for nulls, eep!) :)
Thanks Amy this worked like a charm. I even used it on with a sublayout.
ReplyDeleteThis comment has been removed by a blog administrator.
ReplyDelete