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!

34 comments:

  1. 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");

    ReplyDelete
  2. 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.

    ReplyDelete
  3. 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.

    ReplyDelete
  4. 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

    ReplyDelete
  5. 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 :)

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

    ReplyDelete
  7. 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?

    ReplyDelete
  8. @David

    Yes you are right.

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

    ReplyDelete
  9. @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.

    ReplyDelete
  10. 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.

    ReplyDelete
  11. 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.

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

    ReplyDelete
  13. 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

    ReplyDelete
  14. @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

    ReplyDelete
  15. 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?

    ReplyDelete
  16. 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.

    ReplyDelete
  17. 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,

    ReplyDelete
  18. 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");

    ReplyDelete
  19. 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

    ReplyDelete
  20. 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".

    ReplyDelete
  21. 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

    ReplyDelete
  22. 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.

    ReplyDelete
  23. 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!

    ReplyDelete
  24. While executing i am getting below error

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

    Can you please provide any suggestions?

    ReplyDelete
  25. 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);
    }

    }
    }

    ReplyDelete
  26. How to get all the term sets?

    ReplyDelete
  27. Can you please clear the "_spPageContextInfo.webServerRelativeUrl"?

    ReplyDelete
  28. Hi Vardhaman.

    Thanks for sharing the article and code. This was a great start for what I was trying to achieve by modifying your code.

    ReplyDelete
  29. Thanks a lot for sharing all this valuable information :-)

    ReplyDelete
  30. please help me.. i am delcare in javascript but i have error var context = SP.ClientContext.get_current(); that say "Cannot find name 'SP'" how to declare SP. in type scrpt ?

    ReplyDelete
  31. error
    Specified argument was out of the range of valid values





    function getTerm() {
    debugger;
    var clientContext = SP.ClientContext.get_current();
    var taxSession = SP.Taxonomy.TaxonomySession.getTaxonomySession(clientContext);
    var termStores = taxSession.get_termStores();
    var termStore = termStores.getByName("Site Collection - sp2013dev1-11111");
    var termSet = termStore.getTermSet("17774198-e308-439e-bde4-13e4d5b43e6e");
    var terms = termSet.getAllTerms();
    clientContext.load(terms);

    clientContext.executeQueryAsync(Function.createDelegate(this, function (sender, args) {
    var termEnumerator = terms.getEnumerator();
    //var getItems = new Array();
    while (termEnumerator.moveNext()) {
    var currentTerm = termEnumerator.get_current();
    alert("name" + currentTerm.get_name());
    }
    }), Function.createDelegate(this, function (sender, args) {
    alert(args.get_message());

    }));
    }

    ReplyDelete
  32. Nice blog
    Do you have any example of pnp.js Taxonomy in javascript to extract terms from termset

    ReplyDelete

Comments moderation is turned ON. Your comment might not appear immediately after posting.