Using SPServices with jQueryUI’s Autocomplete Function on InfoPath Forms in SharePoint

Yes, that title says using jQueryUI on InfoPath forms in SharePoint. InfoPath forms are fantastic, except when they just aren’t quite able to do what you want. While InfoPath can help you take your SharePoint list forms to a whole new level, there may be times when you want to add some behavior to those forms which InfoPath simply doesn’t offer.

Guess what? jQuery and jQueryUI can come to the rescue in some of those cases, just as it can with the standard list forms.

I recently worked with a client to do a relatively simple thing, but it was a huge hit. They had a SharePoint list had a Single line of text column, to which the user could add whatever they wanted. However, there was a desire to make suggestions as the user typed, based on the contents of a different list, which had thousands of items.

A dropdown doesn’t make sense in that situation, because there are simply too many items. They also wanted to show matches to what the user had typed, regardless where those characters occurred in the list item.

This is a perfect situation in which to use the idea of autocomplete. We all are familiar with this idea, if not the actual term. You probably see it in action every single day as you use a search engine. As you type your search term(s), the search engine shows suggestions, probably based on some fairly sophisticated algorithms.

Here’s an example from Bing:

image

and from Google:

image

(I can’t help but point out that Google was more on the mark in guessing that I was searching for SPServices, but hey, who’s counting?)

When InfoPath forms are rendered in the browser, they are built of ordinary markup just like any other page, albeit fairly complicated markup, driven by a lot of script.  That doesn’t mean that you can’t add some script of your own as well to add additional capabilities. There are a few peculiarities to this situation, though, which you need to handle.

Here’s a slightly dumbed down version of the script we ended up with.

window.onload = function() {
  window.setTimeout(readyCall, 1000);
}

function readyCall(){

  var externalParties = [];

  $().SPServices({
    operation: "GetListItems",
    listName: "External Parties",
    CAMLViewFields: "",
    async: false,
    completefunc: function (xData, Status) {
      $(xData.responseXML).SPFilterNode("z:row").each(function() {
        externalParties.push($(this).attr("ows_Title"));
      });
    }
  });

  //<input tabIndex="0" title="" class="q_zwfUqJo2fRthHnM4_0 as_zwfUqJo2fRthHnM4_0 b9_zwfUqJo2fRthHnM4_0" id="ctl00_m_g_a226da68_1383_40e3_8410_1ada27d49dcf_FormControl0_V1_I1_T2" aria-invalid="true" style="position: relative;" onfocus="return (TextBox.OnFocus(this, event));" onblur="return (TextBox.OnBlur(this, event));" onpropertychange="return (TextBox.OnPropertyChange(this, event));" type="text" OriginalId="V1_I1_T2" FormId="ctl00_m_g_a226da68_1383_40e3_8410_1ada27d49dcf_FormControl0" ViewDataNode="3" direction="ltr" wrapped="true" ScriptClass="TextBox" VCARD_NAME="91161f891e59461042587839b2504693728ce05a" ?=""/>
  $("input[id$='FormControl0_V1_I1_T2'], input[id$='FormControl0_V1_I1_T3']").autocomplete({
    source: externalParties,
    minLength: 3
  });
}

When InfoPath forms load in the browser, they don’t load with the rest of the page, but instead they are loaded slightly afterward in what amounts to an asynchronous load. Because of that, using $(document).ready(), our trusted jQuery friend, doesn’t work. Instead, as you can see in lines 1-3, we simply wait for 1000 milliseconds (1 second) before we run our script. We found that this was an adequate amount of wait time for our particular form; you might need to adjust this.

In lines 9-19, we use my SPServices library to call the Lists Web Service, using the GetListItems operation. This operation simply reads items from the list based upon the criteria you specify. Once we have the data, we push each of the Title column values into an array called externalParties.

Finally, we call the jQueryUI function autocomplete, using two selectors. In line 21 above, which is commented out, you can see an example of the markup for one of the input elements rendered in the InfoPath form. One of the hardest parts of all of this was to figure out what selector to use. We settled on looking for an input element where the id contained ‘FormControl0_V1_I1_T2’.  (We actually added the autocomplete behavior to two columns in the form, thus the second selector for ‘FormControl0_V1_I1_T3’.)

We added this script into the newifs.aspx and editifs.aspx pages using a trusty Content Editor Web Part (CEWP). Since this was SharePoint 2010, and because it makes for far better code management, we stored the script in a separate file and referenced it using the Content Link.

Bingo-bango, we had a nice, little additional piece of functionality which made the users very happy. This is an example where thinking about all of the tools at your disposal and how you might glue them together into the right solution to get the job done can be the right approach rather than a lot of custom coding.

<UPDATE dateTime=”2011-08-25T23:51″>

My partner in crime for this exercise was Marcel Meth (@marcelmeth), and he’s done a post on it, too, which you can read here. I was able to steal his image of the results, which I’ve added above. Note that the image is not showing the real data but our test data, which was simply a list of the 3000 or so major cities and towns in the US.

</UPDATE>

<UPDATE dateTime=”2011-08-26T09:25″>

I got a question in the comments below about how we added the script to the InfoPath page, and I wanted to add those details here.

  • First, we opened each form in the browser, which launched it in a dialog box.
  • We got the actual URL of the page in the dialog by right-clicking and looking at its properties. The NewForm was newifs.aspx and the EditForm was editifs.aspx (as I mention above).
  • We opened the form page directly in a new browser window and used the toolpaneview=2 Query String parameter trick to put the page into edit mode. This allows you to edit a list form page and add Web Parts to it.
  • We added the CEWP, and put the reference to our script file in the Content Link.
  • Apply and done.

</UPDATE>

Similar Posts

128 Comments

  1. I have created the textbox in infopath ,Here I have used auto suggest control for a textbox, I will load value and ID in that text box , on selecting a value in auto suggest on the textbox an id will be generated for that selected value, I need to store that is in another text box,on post back the stored ID is getting cleared in that text box is there any solution for this.

    window.onload = function() {
    window.setTimeout(getData, 1000);
    }

    function getData(){
    getState();
    window.setTimeout(getData, 1000); //To handle IP’s form postback
    }

    function getState(){
    var state = [];
    $().SPServices({
    operation: “GetListItems”,
    listName: “state”,
    CAMLViewFields: “”,
    async: false,
    completefunc: function (xData, Status) {
    $(xData.responseXML).SPFilterNode(“z:row”).each(function() {
    state.push({label:$(this).attr(“ows_Column2”),value:$(this).attr(“ows_ID”)});
    });
    }
    });

    $(“input[id$=’FormControl0_V1_I1_T22′]”).autocomplete({
    source: state,
    minLength: 2,
    change: function (event, ui) {
    },

    select: function( event, ui) {
    alert(ui.item ? (“You picked ‘” + ui.item.label + “‘ with an ID of ” + ui.item.value) : “Nothing selected, input was ” + this.value);

    $(“input[id$=’FormControl0_V1_I1_T22′]”).val(ui.item.label);
    $(“input[id$=’FormControl0_V1_I1_T23′]”).val(ui.item.value);
    return false;
    },

    focus: function(event, ui){
    event.preventDefault();
    $(“input[id$=’FormControl0_V1_I1_T22’]”).val(ui.item.label);
    return false;
    }
    });
    }

  2. Hi Marc,
    can you review this script and inidcate if there are any issues. I am not getting any errors. I am using jquery-1.11.0 and is that an issue
    Would appreciate a quick response ….thanks for you time

    window.onload = function() {
      window.setTimeout(readyCall, 1000);
    }
    
    function readyCall(){
    
      var acctNames = [];
    
      $().SPServices({
        operation:"GetListItems",
        async:false,
        listName:"FO_Listing1",
       // viewName:"{6A13684D-D7C0B-D4510-D868D-D43CEDFB80099}", 
        CAMLViewFields:"",
       
        completefunc: function (xData, Status) {
          $(xData.responseXML).SPFilterNode("z:row").each(function() {
            acctNames.push($(this).attr("ows_Account_x0020_Name"));
          });
        }
      });
    
     
    //  $("input[id$='FormControl0_V1_I1_T4']")
    	$("ctl00_m_g_13f68922_260c_4a90_b136_fc664795b33a_FormControl0_V1_I1_T4"").autocomplete({
        source: acctNames,minLength:3 });
    }
    
  3. If there is a multiselect dropdown or date field It’s on click resets any jquery settings. I have tried to capture clicks and re implement my jquery . Any clues how to get my jquery at the end of the queue or prevent infopath from over writing my changes ?

  4. Hi Marc,

    I noticed that this is specific to forms in a list (newifs.aspx and editifs.aspx pages).

    How do I add code to form coming from a forms library?

    Will i need to add the form to a web page via the forms content web part and then add the CSWP?

    Thanks,
    Alex

  5. Hi ,

    Hi Marc,

    Would you please let me know the jQuery and Css Files you have used in your code.

    Regards,
    LILU

  6. Hi,

    This solution is exactly what our team is looking to do with an InfoPath form we are building but I have a few questions.

    The form has been built in InfoPath 2010 and published to a SharePoint 2007 library. When user create a new form or edit an existing the must do so using the InfoPath filler functionality.

    Is there anyway to utilize the code/solution outlined here within our setup. Thanks in advance for your help.

    1. SNK:

      For this to work, the InfoPath form has to be published as a Web page using Forms Services. I believe you can do this in SharePoint 2007 as well, assuming you have the appropriate licensing.

      M.

  7. Great article. Can you please add all the necessary links to jquery ui, sp services, css and jquery?

  8. Hi Marc,
    What is the version of Jquery and Jquery UI and Spservice to make it work. I use

    jquery-1.10.2.js

    jQuery/jquery-ui-1.10.4.custom.min.js

    jquery.SPServices-2014.01.min.js

    It only works in Debug mode.

    1. Mary:

      That combination of versions ought to work. It’s impossible for me to test all the permutations, though. I think you’ll need to do some debugging to figure out why it is only working some of the time.

      M.

  9. Marc,

    First of, thanks for the excellent articles and SPServices, I know this article is old, and some might already know this, but if it helps, i figured out a way to improve the jquery selection, in infopath (I’m using 2013 but this might be possible in other versions) if you right click the control, go into properties, and the advanced tab, you can set up the “ScreenTip” which is nothing more than setting the tooltip… which sets the ‘title’ property of the control, that means that you can use this:

    $(“input[title=’myFieldTitle’]”)

    instead of this:

    $(“input[id$=’FormControl0_V1_I1_T14′]”)

    you can see how it’s more manageable and it won’t break if you move the controls in your form, i tested this with a select control (dropdown) but the textbox should work just the same.

    Thanks again for all the work you do for the community!.
    Regards,
    Ricardo

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.