in

Dot Net Mafia

Group site for developer blogs dealing with (usually) .NET, SharePoint 2013, SharePoint 2010, Office 365, SharePoint Online, and other Microsoft products, as well as some discussion of general programming related concepts.

This Blog

Syndication

Archives

Corey Roth [MVP]

A SharePoint MVP bringing you the latest time saving tips for SharePoint 2013, Office 365 / SharePoint Online and Visual Studio 2013.

SharePoint 2013 Autocomplete textboxes using the term store and CSOM

I wanted to create an autocomplete textbox in a SharePoint app recently by using terms from the term store.  Since retrieving items from the term store can be a bit involved I wanted to show you the steps involved.  This solution make use of jQuery UI Autocomplete.  The code loads the terms from the term store and then sets the source.  This implementation is really only ideal for a small amount of terms, but it’s enough to get you started.

For this example, I am going to use a simple set of terms using state names in the United States.  My terms are included in a group named Classification and a Term Set named States.  Here is what my term store looks like.

TermStoreStates

In this example, we’re going to build our code inside a Client Web Part.  Take a look at that post if you are not familiar with the process yet.  We then need to add a heap of JavaScript references.  Some of these are included already, but specifically we need to load SP.Taxonomy.js.  We also need to include init.js as I mentioned in an earlier blog post.

<script type="text/javascript" src="../Scripts/jquery-1.7.1.min.js"></script>

<script type="text/javascript" src="/_layouts/15/MicrosoftAjax.js"></script>

<script type="text/javascript" src="/_layouts/15/init.js"></script>

<script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script>

<script type="text/javascript" src="/_layouts/15/sp.js"></script>

<script type="text/javascript" src="/_layouts/15/sp.taxonomy.js"></script>

My web part is called AutocompleteWebPart.aspx so I am going to add a JavaScript file for my code called AutocompleteWebPart.js.  We also need to include a reference to jQuery UI  You’ll need to download this and include it in your project or pull it from a CDN.

<script type="text/javascript" src="../Scripts/AutocompleteWebPart.js"></script>

<script type="text/javascript" src="../Scripts/jquery-ui-1.9.1.custom.min.js"></script>

Lastly to use jQuery UI, you need to include it’s CSS file in the Content folder of your project.

<link rel="Stylesheet" type="text/css" href="../Content/jquery-ui-1.8.22.custom.css" />

Now, I am just going to add a textbox to the body of our page.

<body>

    <div>

        <input id="autocompleteTextBox" type="text" />

    </div>

</body>

The process for querying terms is involved.  You first need to get a reference to the Taxonomy Session, followed by the Group, the Term Set, and finally you can iterate the terms.  There are a lot of good examples out there but many of them take short cuts by using GUIDs for values for things like the group and term set.  This works but is absolutely useless when you are writing proper code that can be deployed to any environment.  You need to be able to reference these items by name, but unfortunately the API makes accessing anything in the term store by name difficult.  It’s not impossible though, it just requires extra code and iteration.  Let’s walk through our JavaScript example below with absolutely no hard-coded GUIDs.

We’ll start by adding some global variables.  We’ll populate these as we go.

var context;

 

var session;

var termStore;

var groups;

var termSets;

var termsArray = [];

We’ll start in a document ready function.  We use the standard code to get a reference to the current context.  We’ll need this to create a new TaxonomySession object.  We then session.GetDefaultSiteCollectionTermStore() to get the default term store.  From there, we need to context.load on the session and termStore objects.  We then use a typical executeQueryAsync method to execute our query.  The onTaxonomySession method will handle success and we’ll use a shared onTaxonomyFailed method to handle any failures.

$(document).ready(

    function () {

        context = new SP.ClientContext.get_current();

 

        session = SP.Taxonomy.TaxonomySession.getTaxonomySession(context);

        termStore = session.getDefaultSiteCollectionTermStore();

        context.load(session);

        context.load(termStore);

        context.executeQueryAsync(onTaxonomySession, onTaxonomyFailed);

    });

Just like with the managed API, you must configure your Managed Metadata Service Application Client appropriately in order for the default term store call to work.  Click on the Managed Metadata Service Connection and then click Properties.  Now, make sure the checkbox next to This service application is the default storage location for column specific term sets is checked.  Once, you have made this change your code should work.

ManagedMetadataServiceDefaultChecked

The onTaxonomySession method then retrieves a list of groups.  We have to retrieve all groups because there isn’t a method to just retrieve one by name.  Although there is a method to retrieve a group by id.  Since we don’t want to hard code any GUIDs though.  We have to retrieve all groups and iterate them to find the one we want.  A successful query will call onGroupsLoaded.

function onTaxonomySession() {

    groups = termStore.get_groups();

    context.load(groups);

    context.executeQueryAsync(onGroupsLoaded, onTaxonomyFailed);

}

In this method we have a list of the groups so we need to iterate through them and find the one we want.  In this case, Classification.  The code isn’t ideal but it works.  We start by getting an enumerator with getEnumerator().  We then use this enumerator to examine the groups.  In our loop, we use get_current() to get currentGroup.  We then use get_name() to compare against the one we want.  When a match is found, we call another method getTermSets and pass the term set.

function onGroupsLoaded() {

    // iterate termStores

    var groupEnumerator = groups.getEnumerator();

 

    while (groupEnumerator.moveNext()) {

        var currentGroup = groupEnumerator.get_current();

        if (currentGroup.get_name() == 'Classification')

            getTermSets(currentGroup);

    }

}

In the getTermSets method, we call get_termSets.

function getTermSets(currentGroup) {

    termSets = currentGroup.get_termSets();

    context.load(termSets);

    context.executeQueryAsync(onTermSetsLoaded, onTaxonomyFailed);

}

The onTermSetLoaded method will then iterate through the term sets returned and compare by name in the same way.  In this case, we are looking for the term set named States.  When the match is found, we call getTerms().

function onTermSetsLoaded() {

    var termSetEnumerator = termSets.getEnumerator();

 

    while (termSetEnumerator.moveNext()) {

        var currentTermSet = termSetEnumerator.get_current();

        var termSetName = currentTermSet.get_name();

        if (termSetName == 'States')

            getTerms(currentTermSet);

    }

}

This is now the last call we need to make.  This retrieves all of the terms for the term set.  Unfortunately, we have to get all of them (as far as I know) which is why I don’t recommend this with large term sets.

function getTerms(termSet) {

    terms = termSet.get_terms();

    context.load(terms);

    context.executeQueryAsync(onTermsLoaded, onTaxonomyFailed);

}

The onTermsLoaded method will iterate through the terms and add them to an array that the jQuery UI autocomplete method will accept.  There you have it all of the code to get items from a term set without a hard coded GUID.  It’s a lot of code, but not too bad once you get used to it.

Lastly, we’ll get a reference to our textbox and use the .autocomplete() method passing in the value of our array.

function onTermsLoaded() {

    var termsEnumerator = terms.getEnumerator();

 

    while (termsEnumerator.moveNext()) {

        var currentTerm = termsEnumerator.get_current();

        termsArray.push(currentTerm.get_name());

    }

 

    $("#autocompleteTextBox").autocomplete({ source: termsArray });

}

At this point, we are done, but we do need to implement our failure method.

function onTaxonomyFailed(sender, args) {

    alert('Taxonomy Error:' + args.get_message());

}

If you are using this code in an app, the last thing you need to do is set the Taxonomy permission to Read in the AppManifest.xml file.  This will let us query the term store.

AppManifrstTaxonomy

At this point, we can test it.  Deploy your app and add the app part to a page.

AutocompleteExample

So, a little code involved here but the results are great.  You can configure the jQuery autocomplete plugin in a variety of ways too.  This code could probably be optimized some so if you have improvements, let me know.

Comments

 

SharePoint 2013 Autocomplete textboxes using th... said:

Pingback from  SharePoint 2013 Autocomplete textboxes using th...

April 30, 2013 3:15 PM
 

Luis said:

Great post!!!

April 30, 2013 3:22 PM
 

SC Vinod said:

Excellent post bud!!!

April 30, 2013 11:25 PM
 

SharePoint 2013 Autocomplete textboxes using th... said:

Pingback from  SharePoint 2013 Autocomplete textboxes using th...

May 14, 2013 2:03 PM
 

Elizeu Oliveira said:

Is it possible to do the same with external lists?

March 3, 2015 2:03 PM
 

CoreyRoth said:

@Elizeu that should be possible.  You would just query the external list via REST instead.

March 4, 2015 12:07 PM
 

Kelly said:

What about child terms and synonyms?

May 18, 2015 9:41 AM
 

Kelly said:

Also, are there any permissions adjustments that need to occur if this is not a SharePoint Hosted App, but rather a regular SharePoint page (i.e. using JSOM to create a custom responsive SP Form). I don't see where Read permissions can be set.

May 18, 2015 10:07 AM
 

CoreyRoth said:

@Kelly if I remember right, if you call GetAllTerms instead of GetTerms (or their JavaScript equivalent), all terms will be returned instead of just the current siblings.  Synonyms are a different story.  I'd have to think on that.

May 21, 2015 4:40 PM

Leave a Comment

(required)  
(optional)
(required)  
Add

About CoreyRoth

Corey Roth is an independent SharePoint consultant specializing in ECM, Apps, and Search.
2015 dotnetmafia.
Powered by Community Server (Non-Commercial Edition), by Telligent Systems