Skip to main content

External and Internal Links as Items

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!

Comments

  1. Good job, Amy, very interesting post and clear explanation.
    A 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:)

    ReplyDelete
  2. Hi Ivan,

    Thank you for your comment! I'm going to add a more 'universal' redirector to my to-do list (and checking for nulls, eep!) :)

    ReplyDelete
  3. Thanks Amy this worked like a charm. I even used it on with a sublayout.

    ReplyDelete
  4. This comment has been removed by a blog administrator.

    ReplyDelete

Post a Comment

Popular posts from this blog

Using the Source Property

For each of the properties in your template you can set a source for it, this isn’t always used but can improve user experience drastically when done throughout a site. The source field comes in to play whenever you are using any of the following fields: Droplink, Droplist, Droptree, File, Grouped Droplink, Grouped Droplist, Image, Multilist, Treelist, Rich text field and a number of others. There are various ways of setting these up to achieve different results – but in general you are using the source to limit the set of items that can be used, and this requirement can also help you determine what kind of field to use. For example, if you have a Set of items all split down into sub folders and want the content editor to make use of the tree, you could use a TreeList or Drop Tree, but if you just want a set of items without the opportunity to see where those items are – multilists or droplinks are the way to go. For Images you’re generally just specifying where to look for and put th

Web Forms for Marketers: Send Email

To have the save action for your form actually send email, you will need to change one of the settings, otherwise you will receive this error whenever submitting the form: We experience a technical difficulty while processing your request. Your data may not have been correctly saved. Also in your log (/data/logs/newest log file) you will see this error after the form has been submitted: Exception: System.Net.WebException Message: The remote name could not be resolved: 'example.host' Source: System at System.Net.ServicePoint.GetConnection(PooledStream PooledStream, Object owner, Boolean async, IPAddress& address, Socket& abortSocket, Socket& abortSocket6, Int32 timeout) at System.Net.PooledStream.Activate(Object owningObject, Boolean async, Int32 timeout, GeneralAsyncDelegate asyncCallback) at System.Net.PooledStream.Activate(Object owningObject, GeneralAsyncDelegate asyncCallback) at System.Net.ConnectionPool.GetConnection(Object owningObject, GeneralA

Determining Page Editor Status with Javascript

     Often you’ll need to know if you are inside or outside the Experience/Page Editor in order perform an action. If you are on the server-side in code-behind you can check the Sitecore.Context.PageMode to determine which mode you are in. But what about at runtime? Javascript per usual can save the day! Though you can find PageModes through the Sitecore object if it is available to the browser, it may not be there. Depending on how things have been set up with your solution, the Sitecore object may not return a null as would be expected when checking to see if you can access it. Instead Sitecore may be undefined.  Contrary to some examples on the web with only null checks, this quick little change in your script can correctly let you know if you are in the page editor: Just take a look to see if isPageEditor is true or false and you’re set!