Adding a New Item to a Lookup List using JavaScript and SPServices

Update 1/15/2013:  Be sure to read the update at the end of this post.

This post shows how to add a link to an edit form that users can click to add a new item to a lookup list. When the user clicks OK to save the new item, the Information already entered in the edit form is still there, and additionally, the item the user just added to the lookup list is selected in the lookup column.

For the example script, I have a Library called contracts that has a lookup on the Title column of a list called Counterparties.  The following JavaScript can be placed on the Contracts edit form to enable the above functionality.

function setupAddNew() {
    //debugger;

    var selectTD = $("select[Title='Counterparty']").parent();
    if (selectTD.length === 0) {
        selectTD = $("input[title='Counterparty']").parent();
    }
    if (selectTD.length === 0)
        alert("SelectTD not Found")
    if (selectTD.length > 1)
        alert("Multiple select tds found")
      selectTD.append('   ')
    .append("Add Counterparty");

}
function AddCounterparty() {
    var siteUrl = SP.ClientContext.get_current().get_url();
    var options = SP.UI.$create_DialogOptions();
    options.title = "Add Counterparty";
    options.url = siteUrl + "/Lists/Counterparties/NewForm.aspx";
    options.dialogReturnValueCallback = CounterpartyAdded;
    SP.UI.ModalDialog.showModalDialog(options);

}
function CounterpartyAdded(value, returnValue) {
    // if user canceled out of the add dialog
    debugger;
    if (value == '0') {
        return;
    }
    // now refresh the droopdown list of vendors-- if the Vendor List has leess than 20 Items, the dropdown list is rendered as a simple select and we use  field "vendorDropDown",
    // otherwise, it's rendered as a textbox and a hiddentextbox (with some fancy behaviors) and we use fields vendorInput and hiddenVendorInput (vendor input holds the 
    // display value and HiddenVendorInput holsd the ID;
    var lastItemID = $().SPServices.SPGetLastItemId({ listName: "Counterparties" });
    var vendorDropDown = $("select[Title='Counterparty']")[0];
    if (vendorDropDown == null) {
        // more than 20 items, jist zap the values in the text box and hidden field
        var vendorInput = $("input[title='Counterparty']")[0]; // put the counterparty name here when we get it
        var hiddenVendorInputFieldName = $("input[title='Counterparty']").attr("optHid"); // get the id of the hidden itput field
        var hiddenVendorInput = $("input[id='" + hiddenVendorInputFieldName + "']")[0]; // get the hidden input field that will hold the id of the item. This is passed back to sharepoint
          var myQuery = "" + lastItemID + "";
        $().SPServices({
            operation: "GetListItems",
            async: false,
            listName: "Counterparties",
            CAMLViewFields: "",
            CAMLQuery: myQuery,
            completefunc: function (xData, Status) {
                //	$(xData.responseXML).SPFilterNode("z:row").each(function() {  THIS IS THE SYNTAX FOR THE NEWWRE JQERY jQuery 1.7+,  with 
                $(xData.responseXML).find("[nodeName='z:row']").each(function () {
                    vendorInput.value = $(this).attr("ows_Title");
                    hiddenVendorInput.value = $(this).attr("ows_ID");

                });
            }
        });

    }
    else { // Less than 20-- fill the dropdown and select the new item -We must set page.enableeventvalidation to false, because we're adding items to the dropdown
        $().SPServices({
            operation: "GetListItems",
            async: false,
            listName: "Counterparties",
            CAMLViewFields: "",
            completefunc: function (xData, Status) {
                vendorDropDown.options.length = 0;
                var counterpartyType = "";
                //	$(xData.responseXML).SPFilterNode("z:row").each(function() {  THIS IS THE SYNTAX FOR THE NEWWRE JQERY jQuery 1.7+,  with 
                $(xData.responseXML).find("[nodeName='z:row']").each(function () {
                    vendorDropDown.options.add(new Option($(this).attr("ows_Title"), $(this).attr("ows_ID")));
                    if ($(this).attr("ows_ID") === lastItemID) {
                        // counterparty type is "1;#Bank"
                        counterpartytype = $(this).attr("ows_Counterparty_x0020_Type").split(";#")[0];
                    }
                });
                vendorDropDown.value = lastItemID; // set the dropdowns value to the item that was just added. 

            }
        });
    }
}
//$(document).ready(function() {
function documentLoaded() {
    setupAddNew();
    //debugger;
}
_spBodyOnLoadFunctionNames.push("documentLoaded");

The setupAddNew() function finds the lookup column and appends a link to it that will run the AddCounterparty() function when clicked.

The AddCounterparty() function  creates a DialogOptions object to open the NewForm on the Counterparty list. It Sets the dialogReturnValueCallback to CounterpartyAdded so that when the user closes the dialog the CounterpartyAdded() function gets called.

The CounterpartyAdded() function first tests to see if the user clicked the Cancel button on the NewForm dialog and if so, cancels. Otherwise it calls SPServices.SPGetLastItemID to get the ID of the Last Item the user added to the Counterparties list.

Next it check to see if the Lookup field is being rendered as a select (less than 20 items) or an input (20 or more items).

If the input field is being rendered as an input field (i.e. the vendorDropdown is null when there are more than 20 items) it gets the input field that displays the Title of the item to the user and the hidden input field that is used to pass the id of the selected item back to SharePoint. Then it calls SPServices GetListItems to get the item the user just added to the Counterparties List and sets the vendorinput  to the Title of the item and the hidden input to the ID  of the item.

If the input field is being rendered as a select field (i.e. the vendorDropdown is Not null when there are less than 20 items) it  calls SPServices GetListItems to get all the items in the lookup list. It then rebuilds the options of the lookup list and sets the selected item to the item the user just added. If the field is being rendered as a select and we modify the select list the EditForm will throw an error when we attempt to save this. To avoid this error we need to stop Event validation on the page.

Further information can be found here and here

Note : the line in the script above that is not displaying should read:

selectTD.append(‘&nbsp;&nbsp;<img alt=”” src=”/_layouts/images/caladd.gif” complete=”complete”/>&nbsp;’)

Also the line  that reads

var myQuery = “” + lastItemID + “”;

should be

var myQuery = “<Query><Where><Eq><FieldRef Name=’ID’ /><Value Type=’Counter’>” + lastItemID + “</Value></Eq></Where></Query>”;

WordPress wont let me add these!

Update 1/15/2013.

I was asked how to make this work with Lookup columns that allowed multiple values. Aditionally I got tired of making these changes on Multiple Forms and troubleshooting each individually.

So I packaged up the code as a reusable javascript library that you can include in your form pages.  You can download it at http://code.msdn.microsoft.com/Javascript-to-add-an-Add-60b6299b.

I added a lot of error checking to alert you when things were not configured correctly.

To use it you need to add references to  jquery and jquery.SPServices to your page,  as well as a link to this SPLookupAddNew.js.

Then  When the page is ready call SPSetupAddNew for each o fthe columns you want to add a  “add new Item” link to.

function documentLoaded() {     setupAddNew(“System”, “System”, “/Lists/System/NewForm.aspx”, “Title”, “ows_TitleX”, true);     setupAddNew(“Project”, “Projects”, “/Lists/Projects/NewForm.aspx”, “Title”, “ows_Title”, false); } _spBodyOnLoadFunctionNames.push(“documentLoaded”);

The first parameter is the Display name of the lookup column that appears on your New or Edit Form.

The Second parameter is the name of the list that the lookup coluimn is retriveing its data from. (the SOURCE LIST)

The Third parameter is the web-relative url of the NewForm of the SOURCE LIST to display when the user clicks the “Add New …” link

the fourth parameter is the name of the field in the SOURCE LIST that gets displayed  as the Lookup field in the form you are modfying. (Usually Title, if thats the field ytou are looking up)

The Fifth parameter is the ‘ows_name’  of the field in the SOURCE LIST that gets displayed  as the Lookup field in the form you are modfying. (Usually ows_Title, if thats the field ytou are looking up)

If the lookup list has less then 20 Items and it is not a Multi-select, the “add new Item” link will not be displayed because adding a new Option to a Select control would cause an error on PostBack. You can still call the setupAddNew to configure the link, and once there are 20 Items in the lookup list, the “add new item” link will appear.

Advertisements
This entry was posted in javascript, sharepoint, Uncategorized. Bookmark the permalink.

14 Responses to Adding a New Item to a Lookup List using JavaScript and SPServices

  1. Marc says:

    Good work!

    As you probably know, I have a function in SPServices called SPLookupAddNew. That function worked well in 2007, as long as you don’t need to save any of the existing column values.

    In 2010, because of the dialogs (which generally drive me batty, so i turn them off – that framework provides a horrible UX in many cases), we can easily get lost, as I outline in the docs for the function.

    The thing that caused me to stop trying to build a generalized script-only solution is exactly what you ran into at the end of your post. The event validation can’t be controlled from script, so will always throw an error if you try to save with the new value.

    It’s not too hard to do this for a specific instance as you’ve done here. A generalized solution is well nigh impossible.

    M.

  2. russgove says:

    Thanks Marc,
    I’ve used SPLookupAddNew in 2007 and, while it worked, users did often complain about the data they already entered disappearing after they added a new lookup item. The Modal dialogs in 2010 offer an easy way to circumvent this issue.
    I agree that if not managed properly, the lookups can get a user lost. If the If the lookup list’s NewForm has more fields than the list containing the lookup field, the lookup fields NewForm dialog completely obscures the dialog that the user is currently using, and the user will lose context. In these cases I disable dialogs on the list containing the lookup field so that it shows full screen, and the dialogs don’t lose user context.
    But if the dialogs are nested more than one or 2 levels, there’s not much one can do. (Same as in Winforms or other platform I suppose). In these cases dialogs should probably not be used, another UI metaphor is needed.
    Russell

  3. Kamil says:

    Hi Russell

    I need your help. We strive to understand and use your great script.
    Value SelectTD=$(“input [Title = ‘” + fieldTitle + “‘]”). Parent ();
    Server returns value [object Object]
    If set value selectTD = $(“input[title=’Counterparty’]”).parent();
    Server returns a null value.
    And script not work.

    Thanks Kamil

    • russgove says:

      Hi Kamil,
      What version of sharepoint are you running (what patch level_? The recent updates made by Microsoft may have broken this script. The changed the Title attribute of required fields from ‘fldname’ to ‘fldname Required Field’ (breaking a lot of code). You may need to change the selector to $(“input [Title = ‘” + fieldTitle + ” Required Field’]“) to fix it.

      You can just use the F12 developer tools to find the input field and see what its’Title’ is.

      Russell

      • Kamil says:

        Hi Russell

        So I get it completely works. Problem I have with the script until code.msdn
        did not change
        selectTD = $ (“input [Title = ‘” + fieldTitle + “‘]”). parent ();
        for
        selectTD = $ (“select [Title = ‘” + fieldTitle + “‘]”). parent ();
        then it works without problems.

        Thank you

        Kamil

  4. Kamil says:

    Hi Russell

    IE debugger I used. I have a version of Sharepoint 2013 SP1. The first problem was with loading SPservice. I already solved.
    But is displayed in the item Add, can not click on it. How to call

    function AddCounterparty() {
    var siteUrl = SP.ClientContext.get_current().get_url();
    var options = SP.UI.$create_DialogOptions();
    options.title = “Add Counterparty”;
    options.url = siteUrl + “/Lists/Counterparties/NewForm.aspx”;
    options.dialogReturnValueCallback = CounterpartyAdded;
    SP.UI.ModalDialog.showModalDialog(options);

  5. Ismail Abdul-Hadi says:

    Hi Russell,
    I need help with the New SharePoint 2014 June release update the SPAddnewtolookupfield.js is not doing what it suppose to do I change the
    selectTD = $ (“input [Title = ‘” + fieldTitle + “‘]“). parent ();
    to
    selectTD = $ (“select [Title = ‘” + fieldTitle + “‘]“). parent ();
    that solve part of the problem which show the link. now when I add new to the list it is not populating the list and show the added item at the lookup field.

    Can you please help me solving this issue.

    Thanks,
    Ismail

    • russgove says:

      This may be due to the change they made in the Title attribute of required fields (The Title for required firlds is now ‘FieldName Required Field’ instead of just ‘FieldName’).
      If that is in fact the issue, what I’ve been doin to get around it is to just add this to my document loaded event:
      // THIS IS A HACK
      // DEC2010 CU of SP2010 change the Title of all Require Fields to ‘FlnName Required Field’
      // This Hack removes the ‘Required Field’ text from the title
      $(“select[Title$=’ Required Field’]”).each(function () {
      $(this).attr(“Title”, $(this).attr(“Title”).split(” Required Field”)[0]);
      });
      $(“input[Title$=’ Required Field’]”).each(function () {
      $(this).attr(“Title”, $(this).attr(“Title”).split(” Required Field”)[0]);
      });

      • Ismail Abdul-Hadi \(Wirestorm.us\) says:

        Thank you very much for your help.

        I am a new to jQuery. Please excuse me if I am asking too much.

        I have a question where I suppose to add the code below. (which function).

        I replace selectTD = $(“select[Title='” + fieldTitle + “‘]”).parent();

        With

        $(“select[Title$='” + fieldTitle + “‘]”).each(function () {

        selectTD = selectTD = $(this).attr(“Title”, $(this).attr(“Title”).split(fieldTitle)[0]);

        });

        $(“input[Title$='” + fieldTitle + “‘]”).each(function () {

        selectTD = selectTD = $(this).attr(“Title”, $(this).attr(“Title”).split(fieldTitle)[0]);

        });

        It doesn’t work.

        Thanks,

        Ismail

      • russgove says:

        in the documentLoaded function.

        But first check to see if this is your problem. Open your form in Internet explorer. Press F12 to open the developer tools. Then find one of your required fields in the HTML. See if the Title of the field is ‘FieldName Required Field’.

      • Ismail Abdul-Hadi \(Wirestorm.us\) says:

        Thanks, again, I applied the code to documentLoaded function. But it doesn’t work I am not too sure if I follow you correctly.

        The html code I got is “Property

        (None)

        0 Lot East Pine Road

        000 11th Avenue NE, Redmond, Washington

        000 12th Avenure NE, Redmond, Washington

        000 January Ave, Seattle, Washington

        000 Shateau Ave, Sammamish, Washington

        0000 Admin Street, Redmond, Washington

        0000 Market Place’

        Etc…..

        What I am looking for is when the link clicked user fill in the form click save then the lookup field will auto populate with the newly added listitem ( same as what the spAddnetolookupfields.js supposed to do before the last update of sharepoint 2010)

        When click save “000 test Street” shoud show at the property popup field at the 1st image

        Thanks,

        Ismail

  6. Kamil says:

    Hi Russell

    Function Callback fails to refresh. Not changing in script.

    Help me..pleas

    Thanks

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s