
Download the source / wsp at CodePlex
Update June 1st: Version 1.5 released. The new version no longer requires a webpart, nor a lot of configuration, so I've updated the outlines seen in this post. See this new post for more info on the update.
Background
SharePoint document libraries are capable of handling many day-to-day tasks, right out of the box; there's no question about that. When you approach the need or wish for simple to maintain template libraries, that's an entirely different story.
A usual approach is to configure content types, and a set of hard-to-maintain URL links between these and actual documents in other locations. Administrative tasks, such as adding and removing templates, quickly becomes next to impossible, as you'll have to create new content types, and add /remove these manually for each document library you want the templates available in.
Another issue is the fact that the "New" menu for document libraries will show all content types at the root level. You can't categorize them in submenus, so large amounts of templates will be everything but a smooth ride for the end user.
Fixing things with a simple feature
Realizing that the aforementioned widespread pain is completely unnecessary, I set out yesterday to write a feature which can:
- Connect any document library to another document library, with one serving template documents to the other.
- Not require any administration of new templates, other than uploading them to the template library - Instantly making them available to all document libraries linked with the template library.
- Allow document libraries and template libraries to reside in different sites.
- Make the templates instantly, and hierarchically, available from the "New" menu in the document library.
.. And make it all available to all of you, complete with source code, pre-built solution/feature, instructions and documentation.
Installation and Usage
Download the latest source and install packages here.
- Unpack and run the install.bat file from the root folder. This will install the solution, and deploy it to all site collections. If you want more fine-grained control, feel free to install and deploy the .wsp-file on your own.
- Open a SharePoint portal with document libraries you want to template enable.
- Open the Site Settings, and navigate to the Site Feature page.

- Enable "Grep's SmartDocument Template Library Connector"

- Open a document library you want to expose templates in, and open it's settings.

- Navigate to the "Template Library Connector settings" entry, under "General Settings".

- Make sure you select "Yes" to enable template library connections, pick a document library to act as a template library, and save.

- Navigate back to the document library, and verify that the "New" menu is wired up properly.

- Adding new documents to the selected template library will instantly make new templates available from the "New" menu.
- You can optionally add a column called "Description" to the template document library, for additional text under each template, in the "New" menu view. If you wish to call this something other than "Description", the column name can be changed through the webpart settings shown above.
And that should be it. If you've got any questions or problems, feel free to drop me a note through the comments here.
Getting Technical
Writing a solution like this takes a few steps, and a bit of tinkering with undocumented SharePoint libraries. Here's a rough cut of what's covered in the source:
- Utilizing delegate controls to install handlers for all opened pages
- Find all ListViewWebParts on the webpart page, and retrieve entries from its toolbar.
- Adding items to ListViewWebPart's menus
- Adding submenus to the "New" menu
- Adding submenus to submenus
- Utilizing the default SharePoint document template JavaScripts to create new documents
- Retrieving hierarchies from SharePoint document libraries
- Writing and exposing list settings pages
A few of these steps, such as adding menus and submenus, are powered by extension libraries I've included in the source code. A simple thing like adding a submenu to a submenu isn't easily and readily available in the SharePoint object model, but with the extension libraries in the source project, it's ridiculously simple!
Code Pieces
I won't be covering everything here, but some key parts of the functionality, which I haven't seen elsewhere on the web, will be brought forward.
Extending the LiewViewWebPart's "New" menu
The ListViewWebPart has a toolbar, but this isn't immediately accessible from its object model. Why this is so is oblivious to me, as I see many possible benefits of extending the default views.
Ignoring the ListViewWebPart's attempt at hiding it, and the fact that even toolbar access functions are internal, I extended the System.Web.UI.Control class to give me the following edge:
1: public static T FindChildByType<T>(this Control self)
2: where T : class
3: {
4: var stack = new Stack(self.Controls);
5: while (stack.Count > 0)
6: {
7: var control = stack.Pop() as Control;
8: if (control is T)
9: {
10: return control as T;
11: }
12: foreach (Control child in control.Controls)
13: {
14: stack.Push(child);
15: }
16: }
17: return null;
18: }The approach is pretty straight forward: it will do a stack-based iteration of the control class, until a control of the target type is found.
Including this allows you to call a function such as FindChildByType
Once you get an instance of the NewMenu class (which derives from the superbly named ToolBarMenuButton class), you can call functions such as AddMenuItem and AddMenuItemSeparator (see MSDN). There's however no function to add submenus (or submenus to submenus, for that matter), so that will require another extension.
1: public static SubMenuTemplate AddSubMenuAt(this ToolBarMenuButton self, int index, string id, string displayName,
2: string imageUrl, string description)
3: {
4: SubMenuTemplate child = CreateSubMenu(id, displayName, imageUrl, description);
5: self.MenuTemplateControl.Controls.AddAt(index, child);
6: return child;
7: }The key part in the above code is the call to CreateSubMenu, which returns a SubMenuTemplate. The latter is a contruct from the Microsoft.SharePoint.WebControls namespace, which is used for several menus around the SharePoint UI, such as the Site Settings menu you get in MOSS when the "Office SharePoint Server Publishing" feature is enabled.
1: private static SubMenuTemplate CreateSubMenu(string id, string displayName,
2: string imageUrl, string description)
3: {
4: var child = new SubMenuTemplate();
5: child.ID = id;
6: child.Text = displayName;
7: child.Description = description;
8: if (string.IsNullOrEmpty(imageUrl))
9: {
10: imageUrl = "/_layouts/images/MenuNewItem.gif";
11: child.ImageUrl = imageUrl;
12: }
13: else
14: {
15: if (imageUrl.IndexOf("/") == -1)
16: {
17: imageUrl = "/_layouts/images/" + imageUrl;
18: }
19: child.ImageUrl = imageUrl;
20: }
21: return child;
22: }With these functions, along with a few more included in the source project, such as extending SubMenuTemplate to allow addition of nested submenus; adding menus and submenus is easy as pie.
Adding meaningful menu items
Getting to add menu items is one thing, but actually adding something meaningful is what obviously makes it useful. In this webpart, the goal was to make it possible to instantiate document (templates) from other document libraries, and that turns out to be surprisingly simple if you study how Microsoft does regular template instantiation. The javascript function called "createNewDocumentWithProgID" is the key here, and it accepts such parameters as source file url and target folder url. If the menu items are passed calls to this javascript in its click handler, with the correct urls, document instantiation is in the bag as well.
In Closing
So that's about it. Feel free to check the code, use the webpart, develop it further and share alike. For any questions or comments, use the comment feature on this blog.
8 comments:
This is exactly what I've been looking for!!! thanks!!
One problem I am having though is that the submenu does not stay open when mouse over it... it immediately disappears once my mouse leaves the "Templates" entry under New.
Hi Todd.
This is a known issue in SharePoint, and I'll be properly working around it soon :)
See the following link for a temporary fix:
http://templatelibconnector.codeplex.com/WorkItem/View.aspx?WorkItemId=1758
I'm having problems with the temporary fix... Exactly how do I disable the default document templates for the list?
Sorry for such a newbie question but I can't find it on the library's advanced settings page.
I have:
Allow management of content types: Yes
Open in Client application
Display New Folder command on the New menu: No
Allow items from this library to appear in search results: Yes
Todd.
There's no such thing as a newbie question here :) I'm happy to help however I can.
The problem is the content type, I'm afraid. That option will automatically add entries to the "New" menu.
My next update will contain an optional setting to hide Content Type related entries at the root of the New menu, along with a generic fix for the JavaScript issue.
I'll attempt to have both of these available within the next day or so, but I'm fairly pressed for time at the moment - so I hope you can hold your horses for a little while longer :)
Thanks for the clarification. I didn't clear that option becuase I have other Content Types I need there but, I've cleared it for now.
The next issue I'm having is it can not open any of the files. I get the following error once I select a doc and Word opens:
Could not open "http://myserver/Templates/directory/file.doc".
it's missing the subsite, should be looking for "http://myserver/mysubsite/Templates/directory/file.doc"
Everything appears fine in the menuing when selecting the file, so it's mapped correctly, just when it goes to retrieve the file, it's not looking in the right place.
Any ideas?
I have another idea for an enhancement, next... so look out.. :)
Todd.
Could you add a discussion on the security issue on the CodePlex project site (http://templatelibconnector.codeplex.com), and I'll look into it asap.
Sorry for tossing you around, but it'd help me a great deal to gather all issue feedbacks in one place :)
This is freakin' beautiful!! Thanks a million Luv ya!
Hi,
Thanks for sharing the useful functionality. Will this work in SharePoint 2010?
Post a Comment