Wednesday, 19 December 2012

Working with Taxonomy and JavaScript in SharePoint 2013

SharePoint 2013 has introduced some nice new features, one of which is the ability to manipulate managed metadata with the JavaScript Object Model. Unlike SharePoint 2010, we can now do a variety of operations with the Taxonomy Items in SharePoint 2013. Unfortunately, at the time of this writing, there is not a lot of documentation available on MSDN with regards to this particular feature.There is some preliminary documentation available for the Taxonomy in .NET Managed Client Object Model but the JavaScript API Reference has not been updated yet. So hopefully this blog will come in handy for someone looking to explore. All right lets get started:

First and foremost, you will have to load the SP.Taxonomy.js on your page explicitly as it is not loaded by default in SharePoint. Also make sure that you have loaded the SP.Runtime.js and SP.js files before continuing with your taxonomy code. Various errors like "SP.Taxonomy is not defined" or "Unable to get property 'TaxonomySession' of undefined or null reference" might come up if you have not loaded all the 3 necessary files on your page.

A simple way to load all the 3 files is with the jQuery.getScript function:



Now lets see some actual code which you can use to Manipulate the Taxonomy Items:

1) Query a particular Term Set and get all the Terms under it:




2) Create new Term Group under the Term Store:




3) Create new Term Set under a Term Group:




4) Create new Term under a Term Set:




5) Get Value of a Single Value Taxonomy Column in a List:




6) Get Values of a Multi Value Taxonomy Column in a List:




Hopefully you found this helpful. Happy SharePointing!

29 comments:

@tstojecki said...

Excellent article, thanks!
For getting a term set or a term is guid your only option rather than the label?

termStore.getTermSet("b49f64b3-4722-4336-9a5c-56c326b344d4");

Vardhaman Deshpande said...

Thanks Tomasz!

Yes, if you have to get a single Term Set or a Term, I am afraid you have to use the GUID.

But if you are ok with a collection being returned (TermSetCollection) then you can use the termStore.getTermSets(termSetName, lcid) method.

This will return a collection matching your label, which you will have to iterate through to get your required Term Set.

Same is the case with Terms. There you will have to use the termSet.getTerms(termName, true) method which will return a TermCollection which you will have to iterate.

Still, I may have missed something so please let me know if you find anything more. I will love to update the blog as more information comes in.

@tstojecki said...

Thanks!
I am not spending as much time as I would like on 2013, but I will be sure to submit comments once I put my hands on it and find anything worth mentioning.

Joe said...

Hi, This is a great article.

I was wondering how you accessed the API for the SP.Taxonomy.js file. I cannot find the references for that and am wondering on some of the functions available.

The link below has the javascript API reference for 2013, but Taxonomy is not included

http://msdn.microsoft.com/en-us/library/jj193034.aspx

Thanks

Vardhaman Deshpande said...

Hi Joe Thanks for your comment.

Yes at this time there is still no JavaScript API provided on MSDN for the SP.Taxonomy.js

I wrote this article by looking at the SP.Taxonomy.debug.js directly in the _layouts/15 folder and also referencing the API for the .NET CSOM.

Had to do a lot of cross referencing :)

Anonymous said...

why i am not able to see your code in your post?

David Lozzi said...

Thanks for your work, this is beyond frustrating how little MS has provided on this.

One thing in your code, surprised no one else reported this, but I had to put a / in the path before _layouts, i.e.

var scriptbase = _spPageContextInfo.webServerRelativeUrl + "/_layouts/15/";

Difference between base URL and other site collections possibly?

Vardhaman Deshpande said...

@David

Yes you are right.

My web's server relative url is just "/" so I did not need the extra "/" before the _layouts.

Vardhaman Deshpande said...

@Anonymous,

You are probably trying to view the blog in an RSS reader. I use GitHub's Gist to display code which has a known issue of not working with RSS readers.

Sorry for the inconvenience.

Anonymous said...

Excellent Article!
How can I get the site's current navigation Term? I have managed navigation enabled for the site. When on a page I need to get the current navigation term for the page.

Vardhaman Deshpande said...

You can get that using the Server Object Model:
http://www.lifeinsharepoint.co.uk/2013/04/02/quick-tip-sharepoint-2013-managed-navigation-term-current-page-code/

Anonymous said...

Thanks Vardhaman!
But is there a way to get the current pages navigation term using jquery/client object model(you described above using SP.Taxonomy.js) and not server side model.

Vardhaman Deshpande said...

Not as far as I know sorry.

Gil Akiva said...

Hey,
How can I get the friendly URL of the term?

Anonymous said...

Hi

i copied your exact code and replaced the names and guid with mine, i am getting following error. What i am doing wrong , can u help

Specified argument was out of the range of valid values. Parameter name: index

thanks

Vardhaman Deshpande said...

@Anonymous

It's hard to determine what could be wrong without looking at the code. Can you post your question and code on a SharePoint forum like StackExchange?
http://sharepoint.stackexchange.com

Anonymous said...

Hey Vardhaman, I just stumbled across your solution here, awesome writeup, but I do have a question.

Is there a way to return a variable from the execOperation function. I would like to get the label of a Managed Metadata column and then display it within a local function.

I can alert() my Managed Metadata label within the execOperation function, but if I try to return it to the function containing the GetScripts, I cannot get the value. Nor from my originating function. Thoughts?

Vardhaman Deshpande said...

There will not be a direct way to return a value from the executeQueryAsync function as its an AJAX function. You might probably want to use common variables to pass the data.

Kashif said...

Nice article, at least it helped me understand the bits. But my "context" is different than my site collection. Context is http://myprefix-332233.my.domain.com/TestApp/Default/Page whereas I am suppose to fetch term store collection from my site collection http://site.domain.com/. How would that work? I tried creating an appcontext and passing that but it fails. Any help would be greatly appreciated. Thanks,

Kashif said...

resolved, instead of doing getting term store by name, i get the default site collection term store. hope this helps someone.

var termStores = termSession.getDefaultSiteCollectionTermStore();
var termSet = termStores.getTermSet("83be3427-9474-4b46-bc9e-2b0ca75fbd95");

Andrew said...

get pages current navigation term via javascript

var ctx = SP.ClientContext.get_current();
var web = ctx.get_web();
//get nav termset for current web
var currentTermSet = SP.Publishing.Navigation.TaxonomyNavigation.getTermSetForWeb(ctx,web,"CurrentNavigationTaxonomyProvider",false);

//get term for current URL


ctx.load(currentTermSet);
ctx.executeQueryAsync(
function() {
var currentTerm = currentTermSet.findTermForUrl(window.location.pathname);
ctx.load(currentTerm);
ctx.executeQueryAsync(
function() {
//save to global window.currentTermId = currentTerm.get_id();
setUrlsByTerm(window.currentTermId);
},function (sender, args) {
console.log('error retrieving term');
}
);
},
function (sender, args) {
console.log('error retrieving termset');
}
);


hope that helps

Carl in 't Veld said...

One can retrieve the configured simple url by querying the local custom properties using the function get_localCustomProperties on the term object. You will find a key that is called "_Sys_Nav_SimpleLinkUrl".

canperk said...

Hello, everthing works fine when I call this function once in single page. But if I need same function twice at "same" page It says fatal error "The collection has not initialized...." I use it on single page application and it is not working when i change route and turn back where i used that function. Just working once and when i refresh the page

SaMolPP p said...

Hi,
thanks for the great article .
I tried to iterate through the childterms from a parent term within a termset using power shell.
but it didn't work. I used
mterm.getallterms(); method..
but I am getting the error,getallterms is not defined.

Ruth J said...

Thanks for your comprehensive article. Hugely valuable, as there is still a distinct lack of JS CSOM code on the Microsoft sites!
At last i feel like I have a good start point for walking the tree of nodes in my SP App.
You are my Blogger of the week!

student zone said...

While executing i am getting below error

"SCRIPT438: Object doesn't support property or method 'get_path' "

Can you please provide any suggestions?

Raj said...

hi Vardhaman. Thanks for sharing nice article. worth reading it.

i am having one issue. the enumerator object is throwing error when i tried to get multi select meta data column values.

below is the async success method code. where collListItemTopics is list item collection which was loaded before calling async function.

function onQuerySucceeded(sender, args) {
var listItemEnumerator2 = collListItemTopics.getEnumerator();
while (listItemEnumerator2.moveNext())
{
var oListItem = listItemEnumerator2.get_current();

var taxEnumerator = oListItem.get_item(colTopicName).getEnumerator(); //error here//

while(taxEnumerator.moveNext())
{
var currentTerm = taxEnumerator.get_current();
var disText = currentTerm.get_label();
alert(disText);
}

}
}

ARUN said...

How to get all the term sets?

dilip verma said...

Can you please clear the "_spPageContextInfo.webServerRelativeUrl"?