16 thoughts on “Accessing Taxonomy Term Store with JSOM

  1. Bonjour à tous..(hi everybody)
    First thank you for this very interresting code,
    I am new in javascript because that is the first function that i did in this language..
    recursive function and assynchron call in a while loop cannot work..(maybe i am wrong)
    My code works but it s not finished, i explain:
    For iterate from default termstore to Termset Level i used a combination of iteration and lock flag.

    /*————————Fonction lecture du Default Term Store———————————*/
    function onreadDefaultTermStoreSuccess() {
    //——-Infos sur le Term Store
    //var termStoreID = defaultTermStore.get_id();
    //var termStoreName = defaultTermStore.get_name();
    var groups = defaultTermStore.get_groups();
    context.load(groups);
    //—–depart la requete asynchrone.
    context.executeQueryAsync(function onreadTermGroupsSucces() {
    //récuperer l’énumerateur des groupes.
    var groupsEnum = groups.getEnumerator();
    //créer un timer qui vérifie que la requete précedente est terminée.
    groupsInterval = setInterval(function () {
    if (GroupsbusyIndicator === false) {
    GroupsbusyIndicator = true;
    var hasGroups = groupsEnum.moveNext();
    if (hasGroups) {

    var currentGroup = groupsEnum.get_current();
    context.load(currentGroup);
    context.executeQueryAsync(function () {
    var termSetsCollections = currentGroup.get_termSets();
    context.load(termSetsCollections);
    context.executeQueryAsync(function () {
    var termSetsCollectionEnum = termSetsCollections.getEnumerator();
    //préparer ici un second timer pour intégrer la fonction recursive
    /*—————————–TIMER——————————–*/
    termSetsInterval = setInterval(function () {

    if (TermSetsbusyIndicator === false) {
    TermSetsbusyIndicator = true;
    var hasTermSet = termSetsCollectionEnum.moveNext();
    if (hasTermSet) {
    var currentTermSet = termSetsCollectionEnum.get_current();
    var termsCollection = currentTermSet.get_terms();
    context.load(termsCollection);
    context.executeQueryAsync(function () {
    var termsEnum = termsCollection.getEnumerator();

    while (termsEnum.moveNext()) {
    var currentTerm = termsEnum.get_current();
    var termName = currentTerm.get_name();
    var termId = currentTerm.get_id();
    result += termName + “\n”;
    globalTerms.push(new TermJs(currentTermSet, termName, termId));
    }
    TermSetsbusyIndicator = false;
    }, onloadTermsCollectionFail);
    } else {
    clearInterval(termSetsInterval);
    GroupsbusyIndicator = false;
    TermSetsbusyIndicator = false;
    }
    }
    }, 100);
    /*—————————–TIMER——————————–*/
    }, onloadTermSetsCollectionFail);
    }, onloadCurrentGroupFail);
    } else {
    clearInterval(groupsInterval);
    GroupsbusyIndicator = false;
    $(“#resultat”).html(globalTerms);
    }
    }
    }, 100);
    }, onreadTermGroupsFail);
    }
    /*————————Fin Fonction lecture du Default Term Store———————————*/

    and when i arrive to term level instead recursive call i use javscript object model like this!

    function TermJs(currentTermSet, Name, Guid) {
    this.Guid = Guid;
    this.Name = Name;
    this.currentTermSet = currentTermSet;
    this.currentTerm = null;
    this.LoadYourChilds = function LoadYourChilds() {
    this.TermJsCollectionEnum = this.SPTermsCollection.getEnumerator();
    while (this.TermJsCollectionEnum.moveNext()) {
    this.TermsJsCollection.push(new TermJs(this.currentTermSet, this.TermJsCollectionEnum.get_current().get_name(), this.TermJsCollectionEnum.get_current().get_id()));
    }
    }
    this.LoadYourself = function LoadYourself() {
    this.TermsJsCollection = new Array();
    this.SPTermsCollection = this.currentTerm.get_terms();
    context.load(this.SPTermsCollection);
    context.executeQueryAsync(Function.createDelegate(this, this.LoadYourChilds), Function.createDelegate(this, this.failed));
    }

    this.Load = function () {
    this.currentTerm = this.currentTermSet.getTerm(this.Guid);
    context.load(this.currentTerm);
    context.executeQueryAsync(Function.createDelegate(this, this.LoadYourself), Function.createDelegate(this, this.failed));
    }
    this.Load();

    this.failed = function failed(_parameter) {

    }

    I try and my general array with all term set works …but if somebody can explain to me what exactly do “context.executeQueryAsync(Function.createDelegate(this, this.LoadYourself)”
    you are welcome,

  2. Pingback: Extract the Term Sets and their custom properties using CSOM in SharePoint 2013 | The Relentless FrontEnd - Aackose Lal's Blog

  3. Hi,
    I am doing this in a loop. Please find a sample below. In this, for every iteration of the ($eles.each) loop, I want the function to wait and execute the onSucceeded callback method before proceeding to the next iteration. But, somehow, I am not able to get it done, probably because of async call. Can you please help me to achieve this?

    var context = SP.ClientContext.get_current();
    var taxSession = SP.Taxonomy.TaxonomySession.getTaxonomySession(context);
    var termStores = taxSession.get_termStores();
    $eles.each(function() {
    var $ele = $(this);
    var sspID = //getting the Term Store ID here;
    var termSetId = //getting the Term Set ID here;
    var termStore = termStores.getById(sspID);
    var termSet = termStore.getTermSet(termSetId);
    var terms = termSet.getAllTerms();
    context.load(terms);
    context.executeQueryAsync(Function.createDelegate(this, this.onSucceeded),
    Function.createDelegate(this, this.onFailed));
    });

    function onSucceeded(sender, args)
    {

    }

    function onFailed(sender, args)
    {

    }

    • Hi Ven, Thank you for reading my blog.

      I didn’t know the answer to your question and I had to ask my colleague for help as he is much better with JavaScript than myself. You can check out his blog here http://salvatoredifaziosharepoint.wordpress.com/

      His answer was to do something similar to the following (Please note this code is untested)

      var context = SP.ClientContext.get_current();
      var taxSession = SP.Taxonomy.TaxonomySession.getTaxonomySession(context);
      var termStores = taxSession.get_termStores();

      if(eles.count > 0){
      doJob(eles, 0)
      }

      function doJob(array, elementID){
      var ele = array[elementID]
      ...
      context.load(terms);
      context.executeQueryAsync(Function.createDelegate(this, function(){onSucceeded(array, elementID)});
      }

      function onSucceeded(array, elementID)
      {
      var id = elementID + 1;
      if(id > array.count){
      doJob(array, id);
      }
      }

      I hope this helps you.

      • Thanks a lot for your response. But, I am not sure, whether this will work. Since it is asynchronous and within a loop, there is no guarantee that we will get the results in sequence. In fact, can you please let me know, whether the GetRecursiveTerms method works or not? I read and tried the Deferred & Promise pattern, but that works only for the loop, but not for recursion. I am completely stuck now and don’t know how to proceed. Even the CSOM JS gives only a flat structure while calling termset.getAllTerms(). Though, we can use jQuery (SP Services) to call Taxonomy Web Service and get the results directly, this is not recommended by Microsoft. Any help will be highly appreciated.

        • Hi Ven,
          My last example to you should give you the results you were looking for. Although it was still an async call, the next item in the array was called in the async, therefore items would have been in order.
          As I said before I’m no expert in javascript, and unfortunately I haven’t really touched SharePoint 2013 for a good few months now.
          Sorry I cannot help you further. Perhaps when you have solved your problem you could blog about it yourself. Thats normally why I blog something, when I’ve learnt something new.
          Good luck, and if you do a blog to solve your problem leave a link to it in these comments. If you are having a problem there are bound to be others struggling too. Someone at Sharepoint.stackexchange.com might be able to help you further.

    • Bonjour,
      I try to extend this function for loading a javascript object that represent all the sharepoint taxonomy.
      I had not finished today i will start to use the recursive function , for answer the question i found a way for wait that the previous async call have finished is for , i use the set inteval function that check a global variable like this:

      function onreadDefaultTermStoreSuccess() {
      //——-Infos sur le Term Store
      //var termStoreID = defaultTermStore.get_id();
      //var termStoreName = defaultTermStore.get_name();
      var groups = defaultTermStore.get_groups();
      context.load(groups);
      //—–depart la requete asynchrone.
      context.executeQueryAsync(function onreadTermGroupsSucces () {
      //récuperer l’énumerateur
      var groupsEnum = groups.getEnumerator();
      //créer un timer qui vérifie que la requete précedente est terminée.
      var myInterval=setInterval(function() {
      if (busyIndicator!==true) {
      busyIndicator=true;
      var bool= groupsEnum.moveNext();
      if (bool!==false) {

      var currentGroup = groupsEnum.get_current();
      context.load(currentGroup);
      context.executeQueryAsync(function(){
      var termSetsCollections = currentGroup.get_termSets();
      context.load(termSetsCollections);
      context.executeQueryAsync(function () {var termSetCollectionEnum = termSetsCollections.getEnumerator();
      //préparer ici un second timer pour intégrer la fonction recursive
      while(termSetCollectionEnum.moveNext()){
      var currentTermSet = termSetCollectionEnum.get_current();
      alert(currentTermSet.get_name());
      busyIndicator=false;
      //——fin de la requete asynchrone.
      }

      },onloadTermSetsCollectionFail);
      },onloadCurrentGroupFail);
      }else{clearInterval(myInterval);busyIndicator=false;}
      }
      }, 100);
      },onreadTermGroupsFail);
      }

  4. Hi, great post! I have one more question: did you ever manage to Change a property of a termset using jsom?
    I want to Change the IsOpenForTermcreation property.

    • Hi, You wouldn’t believe the troubles I’ve been through to find your answer. As I haven’t opened my 2013 machine for a long time, my Managed Metadata Service wasn’t work. Once I got that working, I had to remind myself of my code. Anyway the answer to your question is yes there is a method.
      As you create your new termset, there is a method called set_isOpenForTermCreation();passing in true or false;

      The way I found out what methods are available was to put a break point in IE after I created a termset, then added the new termset object to watch. Under prototype showed me all the methods available.

      Hope this helps you.

  5. I believe the code above works on Sharepoint 2013 only? Is there any similar way to list the terms in Sharepoint 2010? Thanks.

    • Hi Kourosh,
      Thank you for reading and commenting on my blog. I haven’t tried to search on a Managed Metadata field in SharePoint 2010 or 2013. I have been meaning to look at it, and write a blog on the subject. Unfortunately the only link I have found so for on it is http://msdn.microsoft.com/en-gb/library/ff625182(v=office.14).aspx under examples. Table 2 shows you how to call search via query string against a Managed metadata column. I hope this points you in the write direction.

Comments are closed.