A drop-down menu, the SharePoint way

twolevels

Six months ago, I showed on a simple example how to reuse the default SharePoint drop-down menu. As Larry reminded me, it’s time for me to keep the promises I made and share more advanced solutions.

The solution I am going to detail adds two features:
– two levels instead of one
– the menu items are pulled from a SharePoint list

Visit my SharePoint site for a live demo.

There are various ways to pull content from a SharePoint list. I have chosen to use SharePoint Designer and the Data View Web Part for this example, as it is very convenient when working with grouped items.

Step 1: building the list

Here again you have various options, my preferred choice is to start from scratch and use a custom list.

We’ll need the following columns:
– Title: for the item title
– Description: text column
– Link: a text column for the hyperlink
– Icon: a text column for the link to the item icon
– Category: a column that we’ll use for grouping items.

An example from the above picture:
– Title: Cleverworkarounds – Welcome
– Description: Authority: 27
– Link: http://www.cleverworkarounds.com/
– Icon: /Utilities/Technorati.gif
– Category: Authority: 25 to 29

As you can see, a text column is more flexible than a hyperlink column to enter URLs. In the above example, I used a relative path for the icon.

Apply the sorting and filtering rules you need, don’t use grouping options at this point. For my example I applied:
1/ Sort by Category (descending)
2/ Sort by Description (descending)
3/ Sort by Title

Step 2: building the Data View Web Part

If you are not familiar with SPD and the DVWP, I recommend that you start with these references. Note in particular the tip about creating a temporary page.

So let’s create a new Web Part page and add our list. Then open the page in SharePoint Designer in design mode, right click on the list view and select “Convert to XSLT Data View” (again, see these references for details).

In Data view, select the “Common Data View Tasks” pane for the last adjustments.

common-data-view-tasks

We are now going to add the grouping rule. Under “Sort and Group”, select the Category field, and check the following boxes: “Show group header” and “Show group footer”.
headerfooter

Make other changes as needed in the “Common Data View Tasks” pane. For example, I chose to display all items (Paging option).

Our last action in design mode is to select all the column headers and delete them.

Step 3: Adding the code

We’ll now switch to code view to go through the XSLT and make some changes. Note that you can also do this directly through the SharePoint UI.

Update [01/21/09]: because of formatting issues, I have moved the code to the download section of my demo site. Right click on DropDownMenu-1.txt and DropDownMenu-2.txt to download the files.

Search for:

					<xsl:call-template name="dvt_1.body">
						<xsl:with-param name="ParentPath" />
						<xsl:with-param name="Rows" select="$Rows" />
						<xsl:with-param name="FirstRow" select="1" />
						<xsl:with-param name="LastRow" select="$dvt_RowCount" />

					</xsl:call-template>

And replace it with the content of DropDownMenu-1.txt.

Then search for these three templates:

<xsl:template name="dvt_1.rowview">
...
</xsl:template>

<xsl:template name="dvt_1.groupheader0">
...
</xsl:template>

<xsl:template name="dvt_1.groupfooter0">
...
</xsl:template>

And replace them with the content of DropDownMenu-2.txt.

Save your changes and open the page in your browser. You should now see your SharePoint list displayed in the form of a two-level drop-down menu (the SPD design view will not render the menu).

Change the value of the largeIconMode attribute from “true” to “false” if you prefer the small version.

Your drop-down menu will work as is, but you can do some additional cleanup in the XSLT and remove useless stuff.

This post is largely inspired by Tariq’s menu for SharePoint 2003 (in particular the idea to use the group footer). The 2007 version works in both Internet Explorer and Firefox.

75 thoughts on “A drop-down menu, the SharePoint way

  1. Great work! So hear is another question. slightly off topic. I need to create a table of contents. three columns no more than 20-30 items in a column. I want to populate this from a list and use the columns. What I am tring to do is publish infopath forms to a form library. create a webpart page and load the view to this library with just the Name(linked to item) displaying. I know this much can be done, but the list would be 1 column and will become to long to be useful. if I create multiple columns dynamically I want to calculate something like NumRows/3 and column1 first group (1-20) column2 second group (21-40) and last column the remaining items. Also when item are added or removed from the library I want the TOC to update with that.

    I know I could probably create 3 different views, but I want to a void that
    Can something like this be achieved?

  2. Why, when I copy these statements into SPD 2007 is the final

    strMenu += ”;

    always replaced by only

    strMenu += ”;

    (leading of course to problems ..)

    ?

    The only way I can get these in is to go in the browser to the XSLT editor there.

  3. I think I see what’s going on. All the brackets inside strMenu should be escaped (< and >), but my blog editor has translated them. Let me try and fix that…

  4. Another awesome post! Just discovered your blog about two weeks ago, and I’ve used a good chunk of your tips & tricks (mini calendar, expand/collapse buttons, among others).

    This article here, I’ve been searching for something like this for awhile… although, one question… any ideas how to get a menu like this in the navigation bar at the top of the page (using this or something else)? I’m currently using the Headings and Links available in the Navigation options to link to files, and I’d prefer to have subheadings/categories in them, right now they’re all just thrown in there…

    Anyway, again, great site full of great resources! Can’t wait to see what you have planned next.

  5. Thanks Zack 🙂

    In the code you’ll find this line:
    x = document.getElementById(‘MenuPlaceholder’);
    “MenuPlaceholder” is the element I create in the page to host the menu.

    You can use an existing element instead. As an example, I have used ‘GlobalTitleAreaImage’ on my demo page:
    http://www.pathtosharepoint.com/default.aspx
    The menu is now displayed in the top left corner.

    In your experiments, be careful not to overwrite a key control of your page…

  6. Pingback: SharePoint Links and Resources « Steve Mullen’s Blog

  7. Christophe,

    Another great post! Is there any way to call the menu items from a list without using SPD (our IT department won’t let us loose with that here!). Not too worried at this stage about the sub-menus. I’ve implemented your simple list, which is fantastic. Setting that up to call from a list would be the icing on the cake!

    Cheers,
    Adam

  8. Christophe,

    Thanks for the reply. I’ll give it some more thought! In the meantime, my simple workaround is to use the “I need to…” webpart to create my menu dropdown. It doesn’t give me the option to add an icon or a description (or a second level) to the menu, but it is a relatively simple way of creating a dropdown menu from a list.

    I got the idea from Nicola Young’s post on EndUserSharepoint (http://www.endusersharepoint.com/?p=1259).

    Cheers,
    Adam

  9. Can you use some sort of grouping in the “I need to…” list. That might be a workaround for multiple levels.

  10. Do you have an example of creating a multi level menu that pulls from a list without using SharePoint Designer?

  11. Great menu! Question: Can I put more than one of these drop downs on the same page? I’ve tried dropping a webpart connected to a different list on the page, then following your steps, but I get some very odd results (the original menu displays the data from the new one, and the new one displays nothing). Any thoughts as to what I am doing wrong?

    Thanks,
    Brooke

  12. Brooke: if you look at the code, you’ll see that the elements are assigned ids, for example id=”MenuPlaceholder”.
    If you create several menus, you’ll need to assign different ids (for example MenuPlaceholder1 and MenuPlaceholder2, etc.).

  13. Doesn’t work for me. I’ve tried re-naming all the variables in the java as well, for the second menu.

    I appreciate any thoughts you can give this.

    Brooke

  14. Hi Chris,

    Thanks for the code as it worked perfectly for what I needed. I was wondering if it is possible to put 2 or more multi-level drop down lists on the same page? Everytime I add another multi-level drop down and change the code to display, it breaks the first drop-down list added. Please let me know if I am doing something wrong!

    Thank!

  15. Further, when I change the element from “Menuplaceholder” to “menuplaceholder1” for list 1, “Menuplaceholder2” for list 2, etc.

    When you highlight any of the menu’s, the rest drop down with same list. I have changed the element id also for “TwoLevelMenuMain” to “TwoLevelMenuMain1” and “TwoLevelMenuMain2” for the new lists and still having the same issue.

    • Alen, there are several element ids in the script, you’ll need to check all of them to avoid duplicates. For example, replace all occurences of “Menu” with “Menu2”.

      • Thanks Chris, I was able to finally resolve the issue. I had to rename only 2 elements for each separate drop down. Thanks for the code and the help!

  16. Was able to get 2 instances of menu working on the same page. The second menu displays a white box over the menu title. Any ideas how to clear the white box?

    • Hi Debbie,

      Not sure if you ever got a response to this – and my reply is so tardy, it might be irrelevant. But I thought I would respond anyway for the benefit of anyone else facing this issue.

      The fix was rather easy. Replace all the “>” and “<” characters in the javascript portion of the code with “” respectively. (i.e. the section that writes the menu contents.

      That should fix the issue.

      Sam

      • …oops… it appears my text got stripped of code. the characters to replace are ” & g t ” and ” & l t ” (withuot the spaces) replace with “&gt” and “&lt” respectively.

  17. Thanks for this awesome tutorial, and I have had great success using this menu on individual pages.

    However, I want to integrate this menu into the entire site, which I assume would be done by inserting it into the default.master file. However, when i have tried to do this, it hasn’t worked.

    Is there a better way of doing it?

    Thanks!

    Dave

  18. having some issue implementing the process.

    Getting
    Unable to display this Web Part. To troubleshoot the problem, open this Web page in a Windows SharePoint Services-compatible HTML editor such as Microsoft Office SharePoint Designer. If the problem persists, contact your Web server administrator.

  19. Hi,

    Maybe someone can help me 🙂

    – I have created a dropdown menu in MOSS 2007, but I can’t expand the menu, because i use Office 2003… do any of you guys know if there’s a plugin or something available out there… 🙂

    Thanks…

  20. I am getting the following result :: Unable to displat this Web Part.

    I copy pasted everything and going to revert back to my original version but this is odd… I followed everything to a T.

    Made my DVWP, organized it accordingly with my list items. Which came out ok… kind of bland.

    Still in SPD I goto code section Ctrl+F (items above) Highlight from xml open to close and insert new code…

    I did notice a pop up saying something about IE6 (In IE6 the tag cannot contain a tag ??

    I am assuming that I didn’t goto the end of the XML close / ?

  21. Christophe,

    Thanks for your prompt response!

    Quick question what are the doctype and secondary schema you are using? I am thinking this is where my problem may be??? Mine is xhtmal trans/ie6

    Here is the snippet right before I would change it ::
    (took the first
    xsl:with-param name=”Rows” select=”$Rows” />
    xsl:with-param name=”FirstRow” select=”1″ />
    xsl:with-param name=”LastRow” select=”$dvt_RowCount” />

    /xsl:call-template>
    /TABLE>/td>/tr>
    /TABLE>
    /xsl:otherwise>

    When I replace the area between xsl:call-template to the close /
    I get the error…

    Going back through and reading I see this::
    “Our last action in design mode is to select all the column headers and delete them.” ???

    I think I over looked this area… what do you mean delete them? Clicking and deleting each heading?I tried through the Common Data View Tasks and it does not allow all to be deleted.

  22. I can’t open your download docs. I right clicked and saved as target but when I went to open them they were blank.

  23. Just want I wanted – new to Sharepoint and thought they would have stuff like this!!! Got everything working except that when I view the page I can see the column headings. I’ve worked through the instructions lots of times and always the column headings are displayed but can’t see where I’m making the error – can any one help?

    Also I want to expand the navigation to at least 4 levels – can this be done easily? If so, is there anything to watch out for.

    • Adrien, I think you missed one small step in design mode:
      “Our last action in design mode is to select all the column headers and delete them.”
      The technique should work for 4 levels, but I haven’t tried myself.

      • Thanks for the quick response. Didn’t realise it was a matter of just deleting them in SPD. All okay now.

  24. Hello Christophe,
    Is there a way to filter the SharePoint list data display (as links in the menu) based on the SharePoint group to which the logged-in user belongs? If yes, would you please help me with this solution?

    Thanks in advance,
    Phoeni

  25. Christophe,

    Great post!

    Is there a way to NOT open a new window when clicking on the link in the pull down?

    Please advise.

    Thanks very much.

    • Never mind. I finally figured it out.

      In the XSL editor, change:
      onMenuClick=”javascript:window.open(\”+ url +’\’)”
      to:
      onMenuClick=”javascript:window.location.href=(\”+ url +’\’)”

      Thanks again for a great write up.

  26. Christophe, thank you for your posts!

    2-Things..

    First, how do I get this to work with just ONE LEVEL? I have used your ‘simple example’ successfully, but really need to populate it from a SharePoint List (like in this example) – but I don’t require the 2nd level.

    Second, Anthony’s suggestion above to get the link to open in the same window didn’t work for me – can you provide the code snippet for that as well?

    Thanks

    • Anthony’s suggestion should work: replace window.open with window.location.href.
      I have another post with a one level menu, you’ll need to try and combine both to get your result!

      • This is a great help Christophe! I’ve been lurking for a while, and have used a number of your solutions. Thanks!

        Unfortunately, Anthony’s suggestion isn’t working for me either. Is there something else that needs to change beside the code? The link still opens in a new page. Any other suggestions? Thanks!

  27. Is there a way to easily copy and paste the webpart into multiple pages. I’ve tried to do this, but it doesn’t show up on the new pages when copied.

  28. Christophe, thank you for your posts!

    I still need help with this. How do I get this to work with just ONE LEVEL?

    I have used your ’simple example’ successfully, but really need to populate it from a SharePoint List (like in this example) – but I don’t need the 2nd level.

    You suggested I try and combine your two solutions into one – I have failed. Will you combine them into one please?

  29. How would I put a third level or sub cat. in the drop down list so that I can split if off different areas.

  30. @Jeannie and Joanna:
    Jeannie, I just read Joanna’s comment and realized I sent you on the wrong path. Sorry for that.
    Once you have your Web Part, use the export option to save it to your local drive. You can then reuse it on other pages of your site by using the import option. For more information on export/import, see the Microsoft help.
    The article I pointed to is a completely different approach for sharing menus across sites and site collections.

    • Thank you, Christophe! Your blog has been a great help and inspiration to me.

      On another note, how do you add icons to the categories (primary dropdown), as opposed to the submenus?

    • Hey Christopher trying to create a two level drop down menu in sharepoint designer 2010, created the list though I am unable to see xsl:with-param name=”Rows” select=”$Rows” />
      xsl:with-param name=”FirstRow” select=”1″ />
      xsl:with-param name=”LastRow” select=”$dvt_RowCount” />

      /xsl:call-template>

  31. Hello,

    I am working with SharePoint 2010 and I can follow your instructions till I reach the part to replace the content. I cannot find line in the XSLT file. Have you got a SharePoint 2010 version of your script?

    Thanks for all the great work you are doing.

  32. First a quick answer to some of the guys that are asking about using it for one level, if you omit the part about using the group header and footer, and then on download-2.txt just copy the first part (rowview) and not the header and footer it works just fine.

    Now a question. I am using the sample on a master page. I can make it work fine, but if I try to use it on sub-sites it breaks. I believe it is because the SHAREPOINT DATASOURCE is pointing at a LOCAL list, and can’t find it in the subsites. Is there any way to change the settings of the datasource so that it is available to the sub-sites???

    Thanks.

  33. Thanks for the comment Carlos.

    If you build the DVWP wthin the site that contains the list, it won’t work in other sites. What you need to do is start on ANOTHER SITE in your site collection, and create from scratch a DVWP that will use the list as source.
    The resulting DVWP will work on all sites in your site collection.

  34. Thanks for your response Christophe. From what you stated in your answer, if I create a DVWP on a subsite for example, the dvwp should work accross all sites in the collection, however, when I try that, something seems to be missing:

    1) I have to get the list by using the data library, and selecting the parent site, so what I can see the list.
    2) When I include that list on the page, it is inmediately an XSLT Data View.
    3) When I go to the XSLT to modify it, I get an error when inserting the DVT_1.Body XLST. The error states that it can’t find the variable $DVT_rowcount or something to that effect.

    Apparently in the sub-site, I’m now building the list the right way. Can you point me in the right direction????

    Thanks again.

  35. Hello!

    @Krutika: Me too; im unable to download the file. It just displays an empty page.. no code.

    Can we have it in any other way Chris?

    • If you got an empty page, it means that:
      – either you did a left click instead of a right click
      – or you didn’t save it as a .txt extension

      If you do both – right click and save as .txt – you’ll get the code.

  36. First of all, great article! I’m having an odd thing happening, the “Link” isn’t being pulled into the menu. All of the other fields (Title, Description, Icon) are getting pulled in.

    On one menu, renaming the “Link” column to “Test” worked, but that isn’t working for any of the other lists.

    Any thoughts?

  37. Hi Christophe,

    Thank you very much for sharing this, it works great!
    2 questions:
    -For some reason my menu doesn’t dipslay the icons at all. Any idea why that is?
    -How can I change the displayed Menu Title into something else?

    If i change this portion of the xsl code
    serverclientid=”TwoLevelMenu”>Menu Title&lt
    into
    serverclientid=”TwoLevelMenu”>Something Else&lt

    It doesn’t do, it crashes.

    Any ideas?

    thanks
    Vinz

    • Hm, never mind the menu title, I was using “&” which wasn’t parsed correctly, I guess..

      Still remains the issue with icons..

    • Hi Christophe,

      I still can’t get the icons to display at all.
      The path to the pictures is in a text column.

      Is anyone getting the pictures diplayed at all??

      Best regards,
      vinz

  38. Hi Christophe

    I too would like to know how to get the Menu Drop Down to show up in the Top Navigation Bar (next to the traditional Home tab). I tried replacing the “MenuPlaceholder” id with “PlaceHolderHorizontalNav” but it basically does nothing. Any advice would be greatly appreciated. I am not a developer.

  39. Hello Crhistophe, Nice Work!!! thank you for sharing it!!!
    I have tested it, and it works well…

    I have a Question for you, I would like to make my dropdown menu looks different than the regular “site actions” menu.
    ¿Where in the code can I insert some graphic css styles to change its background, type and etc.?

    • The whole point of the post is to provide a no brainer solution that will automatically adopt the look of the site. If you need a custom look, you’re better of doing it from scratch, or with a client side script. You’ll find on the Web lots of free solutions!

  40. Hello, all. Great post and responses!

    I have used this trick to create a dropdown on my dashboard to pull from a list of forms in a library, creating list of hyperlinks to the forms (single-level). For the URL, I am pulling from the @LinkTitle xpath, and have made the appropriate changes to the code provided in DropDownMenu_1.text:

    // Create the menuitem for each item
    var title = ”;

    var url = ”;

    I got it all working except for the fact that when a link from the dropdown is selected, the URL for the page that opens is not complete. For example:

    I have a page @ the following link:

    http://sharepointportal/… …/PlaySite/Pages/Client%20Name.aspx

    However, when I click on the link in the dropdown, the URL is:

    http://sharepointportal/… …/PlaySite/Client%20Name (missing the “pages/” and “.aspx”)

    This gives me an invalid page. I tried doing a combination of sub-string options but that didnt work. Maybe there is somethign to be done with the DDWRT? I am at a loss here, ao any help from anyone woudl be GREATLY appreciated.

    Rudy

  41. Hello Christophe, do you have an example of this in SharePoint 2010 ? I have an exact requirement and have follow your example step-by-step, however in SP2010. It didn’t work. I looked at the code and didn’t see if SP2010 would make any different to the codes, but couldn’t figure out why….if you know of a solution, please let me know. I have googles and search for an answer for days…Thanks much in advance.

  42. Pingback: Collapsable menu in place of quick launch for a subsite | Q&A System

Comments are closed.