Extending Lookup Fields with “Add new item” option
Development, JavaScript, jQuery, Productivity, SharePoint, Tools
How many times were you working with Lookup Fields and just when you were about to pick a value, you found out that it’s not there. How many clicks did you have to make to get to the Lookup List, add the new Lookup Item, get back to where you were first and add your item? While it sounds trivial, it’s the only way things can be done in out of the box SharePoint. You could of course create a whole new Custom Field Type which would contain an “Add new item” link, but there is an easier way to get this done.
Inspiration is just around the corner
A couple of days ago I attended a Dutch Information Worker User Group (DIWUG) meeting. Two great sessions were scheduled for that evening: “Adding new building blocks to SharePoint” by SharePoint MVP Ton Stegeman and “Best practices Excel Services” by C# MVP Dennis Vroegop. It was Ton’s session that inspired me with solving the Lookup Fields challenge.
First things first: what could you do?
Before we focus on what I’ve done to improve the Lookup Fields experience, let’s a have a look at some standard approaches.
Custom Field Type
Probably the very first thing that comes to your mind, when talking about changing the behavior of SharePoint Field Types, would be to create a Custom Field Type. You would inherit from the SharePoint Lookup Field and extend it with an “Add new item” link. While it sounds simple, there are a couple of issues here that you should keep in mind.
As you know SharePoint ships with Lookup Fields and Multi Lookup Fields which allow you to select multiple values. The problem is, that the underlying Field Types are hard coded so once you change the “Allow Multiple Values” setting, the Field Types revert to the standard SharePoint Field Types: so much for inheritance and a Custom Field Type.
Developing Custom Field Types is not easy especially if you want to do it right. Once provisioned, a Custom Field Type is available on all Web Applications in the Farm. This means that a Custom Field Type should be generic, reusable and not depending on any Web Application/Site Collection specific resources. Additionally, while creating a Custom Field Type you have to consider all the different places a Site Column can be used: all List Forms, Page Layout Controls, Grid View, not mentioning the Document Information Panel which doesn’t support Custom Field Types at all.
Creating a Custom List Iterator
All fields on the List Forms are displayed by a very smart control called List Iterator. What it does, is that it iterates through all available Fields in the given List and renders the display/input controls for every one of them. What you could do is to subclass the List Iterator and extend it with some extra functionality which would add an “Add new item” link to every Lookup Field.
The problem with a Custom List Iterator is that you would have to add it to the List Forms of the given List before you can use it. This means that you wouldn’t be able to use any of the standard SharePoint lists: quite a price to pay for something that is supposed to improve the editing experience.
…so let’s extend the List Iterator with a Control Adapter?
You could try to extend the functionality of a List Iterator with a Control Adapter. Basically you would do the same as in the previous approach but then you would implement the logic in a Control Adapter which would automatically apply it to every List Iterator on your site. Unfortunately, also this approach has a couple of drawbacks.
First of all Control Adapters are not very easy to deploy. A Control Adapter consists of an assembly and a .browser file which has to be deployed to the App_Browsers folder in your Web Application’s IIS directory. As deploying to App_Browsers isn’t supported by SharePoint Solution Packages (WSP), you would have to create a Timer Job to get this done properly.
Another thing that you should consider is that a Control Adapter is scoped to a Web Application. Once provisioned, it is being applied to every instance of the given type in given Web Application unless specifically disabled by that very instance. Not surprisingly 99,9% controls don’t disable Control Adapters what means that you could extend List Forms that you didn’t want to customize in the first place.
What about <SomeOtherApproach>?
The great thing about SharePoint is that you can do almost anything in numerous ways. I’m quite sure there are some other approaches which you could try to get this done. As long as they involve custom development, I’m quite sure they would get too complex very soon. While adding a simple “Add new item” link to a Lookup Field sounds easy, it isn’t – at least unless you get out of the development box.
How I got inspired
In his presentation Ton discussed some customizations he did for a few of his customers. All of those customizations had one thing in common: they could’ve been done using the standard approach that involves custom development. Instead Ton used a combination of JavaScript/jQuery and SharePoint Delegate Controls to get the job done – the easy way.
In one of the cases Ton presented a Lookup Field with an “Add new item” link. In the case, that Ton discussed, the link was attached to a specific Lookup Field. That’s when I got inspired: why not take that concept and use it to create a generic solution that would work for every Lookup Field…
The requirements
While thinking about the solution I’ve defined some requirements.
Support standard Lookup and Multi Lookup Fields
The very first requirement that I defined was that the solution would have to work with the standard SharePoint Lookup Fields: both single and multiple choice. No Custom Field Type should be developed.
Support different Lists
The solution would have to be generic enough to work with every Lookup Field within the given Site/Site Collection. As every Lookup Field can retrieve data from a different List the solution should make it possible to define the target List for the “Add new item” link.
Be end-user friendly
While I could include the “Add new item” link in the solution itself I though that it would be better if it was possible to define the text for every Lookup Field separately. Like this you could add an “Add new Category” link to a Lookup Field that allows you to pick a Category instead of a standard “Add new item” link.
Support Content Types
Depending on your scenario the items in the Lookup List might consist of only the Title, but they might be more complex as well. The solution should support all kinds of content. Additionally if the Lookup List contains items of multiple Content Types the solution should allow you to define which Content Type you want to use while adding new item.
The solution
The solution I came up with was the same one Ton discussed in his presentation: to use a SharePoint Delegate Control which would include some JavaScript to get the job done.
The most challenging part was how to complete all the different requirements while working with nothing more than standard SharePoint Lookup Fields. To get the job done I decided to use the Field’s Description to store all the information required by the “Add new item” link.
Adding the “Add new item” link
Before you start extending your Lookup Fields with “Add new item” links, you have to activate the Imtech Extended Lookup Fields Feature. Depending on your scenario you can activate adding the links either for a particular Site or a whole Site Collection. After you activated one of the two Features you can proceed to configuring your Lookup Fields.
In order to provide all the required information to the JavaScript script I came up with the following syntax:
List=ListUrl;Label=Link Text[;CT=Content Type ID]
for example:
List=/Lists/Categories;Label=Add new Category;CT=0x01001234
The List parameter contains a valid URL to a List. The URL of the List New Form (/NewForm.aspx) is being appended to that URL.
The Label parameter contains the text that is being displayed as the “Add new item” link. That text can contain any chars except the ; (semicolon).
The last parameter – CT is optional and allows you to provide the ID of the Content Type that you want to use to add new item to the Lookup List.
And that’s all you really need to extend your Lookup Fields with an “Add new item” link. A working SharePoint Solution Package is available on CodePlex. As the solution doesn’t contain any custom code you can explore the source by changing the package’s extension to CAB and exploring its contents.
Download: Imtech SharePoint Extended Lookup Fields (23KB, WSP)
















October 4th, 2009 at 5:58 am
Waldek:
This is a very cool idea. I hope you don't mind, but I'm borrowing the idea for our jQuery Library for SharePoint Web Services (http://spservices.codeplex.com). By using the Web Services, we can make this work without having the user provide the List and Label in the Description.
Our new function SPServices.SPLookupAddNew will be called like this:
$().SPServices.SPLookupAddNew({
lookupColumn: "Region Name", // The display name of the Lookup column
promptText: "Add new " // Text to use as prompt + column name
});
M.
October 4th, 2009 at 5:07 pm
@Marc: great to hear it's something you can use
October 5th, 2009 at 8:23 am
Waldek,
what a nice, simple and clean solution! This inspired me to realise some other things that I have mind.
October 9th, 2009 at 1:20 pm
oh much thanks, Waldek! That's great and easy solution!
October 9th, 2009 at 8:43 pm
Is anyone else having problems getting this javascript to work in IE? It works fine in FireFox and Opera but I get nothing in IE8
October 9th, 2009 at 11:28 pm
@Matt: IE8 is the only browser I've tested it with to be honest. Sure you're not having cache problems? Do you see any JavaScript errors?
October 12th, 2009 at 7:51 pm
I think the problem was the complexity of the selector statement. Your downloadable source includes this line:
$("#onetIDListForm select[id$=Lookup]").parents("td.ms-formbody").each(function() {
I had to change that line to this to get it to work:
$("td.ms-formbody").each(function()
I'm sure that my selector is less elegant, gets a few more elements and does require more work. But it works on all of the machines and all of the browsers I tested it on.
I wonder if an element of complexity was that I have three lookup fields on the same form I was testing with? I didn't try having only a single lookup on the page.
October 12th, 2009 at 10:35 pm
@Matt: I'm really surprised you got it working in FF but not in IE. I would suspect something like a difference in selector to depend on some SharePoint Features but not on a browser, especially with a framework like jQuery.
I have tried it on three fields myself (two single select and one multi select). It worked okay, so the difference should be in the HTML rendered by SharePoint. Different ServicePack perhaps?
November 4th, 2009 at 2:17 am
I am trying to use this feature for a multi-select list option scenario, but after activating the feature,I am unable to use the multi-select list option lookup control. Is there a way to fix this? I am using IE-8 in my dev. box.
November 4th, 2009 at 7:45 am
@Phoenix: do you have any more details about the error you're getting?
November 5th, 2009 at 12:22 pm
Waldek: I am unable to use the lookup control at all. Once I select the item from left list box, when I click on button to move the item to right listbox, the item doesnt move at all. Is there any code change required?
November 5th, 2009 at 2:44 pm
Hi Waldek, same here. It seems to work fine with single lookup but not multiple. No JavaScript-errors afaik.
November 9th, 2009 at 10:43 am
Waldek: Any update on this resolution? I am relying on this option and hence can you pl. let me know if you have a resolution?
November 9th, 2009 at 11:07 pm
@Phoenix: I've managed to solve the issue. It had to do with altering the html source using the jQuery html() function. Here is the new code (remove the var link = '…'; and add instead):
this.lastChild.data = "";
var div = document.createElement("div");
div.setAttribute("style", "padding-top: 5px");
div.innerHTML = '<img alt="" src="/_layouts/images/setrect.gif" style="vertical-align: baseline"/> <a href="' + lookupList + '/NewForm.aspx?Source=' + escape(location.href) + '" rel="nofollow">' + label + '</a>';
this.appendChild(div);
November 10th, 2009 at 3:53 am
Nice post Waldek !. Is there a way to get your code working for a Document library lookup ? There is this lookupID which is required for upload.aspx – which I am not sure how to achieve using your code.
Can you please help?
November 10th, 2009 at 8:04 am
@Suzz: do you mean the URL of the upload.aspx page? The only thing I've noticed there is the List ID and the URL of the RootFolder. Could you explain a bit more what is it that you would like to achieve?
November 10th, 2009 at 8:58 am
Yes Waldek !. you are correct. I am trying to hook a multiple lookup from a document library within SharePoint list, so that users can upload the document and then further provide SharePoint list data. How do I achieve this scenario? How do I get the List ID?
November 11th, 2009 at 8:51 am
@Suzz: I've just browsed through the rendered HTML and it seems like there is no variable that points to the list ID. There are some links inside the page that contain the list ID but I'm not sure if it's a reliable way to obtain it.
November 26th, 2009 at 1:06 am
What a fabulous solution! I have a very complex series of related lists and this was just what I needed.
However, I've run into a snag. It's working fine on a couple of lists, and it was working on a Request list I have, but suddenly it's stopped working for the Request list. I added a custom Display form, but the New and Edit forms are the defaults. I am also using content types. Any ideas as to why this would stop working suddenly? If you can help, I'd really appreciate it as the whole solution is depending on this.
November 26th, 2009 at 1:27 am
I also tried the code above to fix the multiple lookup issue, but now nothing is working. No link, just the code showing as the description of the form.
November 26th, 2009 at 2:02 am
Ok, even odder. It works for some fields on the same form, but not others! I\'ve tried deleting the description and re-adding it. I\'ve copied the exact same description from one field that is working, and copied it to another. It is not making any sense.
November 26th, 2009 at 8:39 am
@Elizabeth: Have you customized anything about either the Master Page or the List Form? The solution uses a Delegate Control to hook up JavaScript. If the Delegate Control is missing in your Master Page, the control can't get attached. Also, if you have changed anything about the List Form, it might happen, that your HTML is different than default SharePoint HTML and is not being picked up by the JavaScript selector for rewriting.
November 26th, 2009 at 4:31 pm
Elizabeth:
Not to "steal"anyone from Waldek, but you could try my jQuery Library for SharePoint Web Services (http://spservices.codeplex.com) solution (first comment above). Folks have been using it with no issues. I've added more options, so it's pretty flexible.
M.
November 27th, 2009 at 4:56 am
Thanks for the suggestions. Unfortunately, I haven\'t customized anything on the forms or master page so that\'s not it. The odd thing is that it works on some of the fields on the page but not others (all on the same page). And it\'s consistent across both the new and edit pages (the default Microsoft ones).
The only thing I can think of is that I\'m still testing and I deactivated then reactivated the solution. I think the ones I added before I deactivate/reactivate are the ones not working, and the ones I added afterwards are the ones working.
December 3rd, 2009 at 8:31 am
@Elizabeth: as far as I can tell, the DelegateControl that I'm using shouldn't 'hang'. I think you would just have to do some more debugging as it's quite odd that it works for some fields but it doesn't for other. Perhaps there is something different about the non-working fields as for how the HTML is being rendered?
December 8th, 2009 at 7:11 pm
@Waldek: Thanks for the suggestions – I ended up using the JQuery solution Marc suggested and that worked.
December 8th, 2009 at 7:21 pm
Elizabeth:
Glad to hear my solution worked for you! (I can\'t tell if you\'re one of the Elizabeths I\'ve been corresponding with.)
M.
December 8th, 2009 at 8:37 pm
@Elizabeth: Great to hear you got it working.
@Mark: Thanks for the assistance
January 5th, 2010 at 1:17 pm
I have the same problem as Phoenix. Can you tell me where I have to change the code? I need the sources for that? Thanks!
January 5th, 2010 at 4:17 pm
@zerabba: see comment
January 9th, 2010 at 11:14 pm
Hi Waldek,
I am a novice trying to get to grips with WSS 3.0
I need the facility for adding addtional items to lookup field and have downladed and deployed the wsp on my site using the stsadm utility.
I know it is a silly question but, how do I use it?
Is ther anything I have to do in the site settings to apply your code?
A step-by-step procedure would be greatly appreciated.
Thanks in advance!
January 10th, 2010 at 4:24 pm
@Tony Caballero: You said you have deployed the WSP. Have you also activated the Feature in the Site (Collection) Features? The last thing that you need to do is to edit the description of the particular Lookup Field as shown in the images in the article above.
January 10th, 2010 at 7:14 pm
Hi Waldek,
Thanks for your prompt response (even on a sunday!).
I did deployed and activated the Feature and it shows in Central Administration.
However, I did change the Feature name slightly before I deployed it,(renamed to: ExtendedLooupFiedls.wsp).
Since then I have tried to retract it and this error error shows in Solution Management:
extendedlookupfields.wsp Error Globally deployed.
Now when I try to redeploy it again, I am told that the application is already activated.
Not sure what to do now…
Thanks
January 10th, 2010 at 7:58 pm
Hi,
Back again, I have managed to remove the feature (I found an excellent link about using stsadm to remove failed solutions) so I have re-applied again, this time without renaming the Feature. It shows as Active in Site Collection Features.
I dont understand from the text above where do I make the changes for the LookUp field?
I have a list named Customers and a List called Support Calls, in Support Calls I have a lookup field that picks the company name automatically from the Customer's list.
Could you please give me a simple "idiots guide" of where do I make the changes to utilize your Feature.
If it is too much bother, please say so and I will go away
Thanks in advance.
Antonio
January 10th, 2010 at 9:24 pm
@Tony: you have to edit the particular Lookup Field and then edit its description as described in the "Adding the “Add new item” link" section in the article above.
January 11th, 2010 at 11:53 pm
Hi,
If I put any content in the Lookup description field such as:
List=/Lists/Categories;Label=Add new Category;CT=0×01001234
This text appears in beneath the Field when I insert a new item.
I think I am being totally thick here, but I cant figure it out…
Is there any other examples I can see… please?
January 15th, 2010 at 7:01 pm
I am seeing the same issue as Tony – I am finding the text below the insert field showing the link and the label under the link.
February 23rd, 2010 at 6:45 pm
Great solution! Can you publish the updated version on Codeplex? (Update allowing selections to be added based on http://blog.mastykarz.nl/extending-lookup-fields-add-new-item-option/#comment-33603)
I'm also wondering if the rest of the data in the form can persist after adding a new lookup item. The entire form is cleared otherwise.
Thanks!
February 23rd, 2010 at 7:18 pm
@The Wire: We're having the exact same issue with data persistance. That would be a great addition to this functionality. The clearing of the form is really bothering our users.