Using JSOM to query SharePoint 2013 lists with Taxonomy Fields

So, I’d an interesting problem. I have a SharePoint 2013 list that uses a Managed Metadata (or ‘Taxonomy’) field. I need to, through the JavaScript Client Object Model, get all items that have a particular value or a child of that value on the taxonomy tree. As an example, here’s my taxonomy:termSet Sounds like it should be simple to query this, right? Well, not so much. The first problem that I had was get the children of the node that we wanted to query by. This didn’t seem possible to query by in CAML, so I was going to need get a set of all the ‘valid’ nodes of the taxonomy. However, getting that set of nodes is … tricky. In theory, you should be able to take the selected node, and recurse over the child nodes, getting their IDs. The Term.getTerms() function suggests this is possible – but the documentation tells you nothing about how to actually use it. I simply couldn’t get this working, and to be honest, I was concerned about potentially making LOTS of JSOM requests to traverse this tree. Instead, I realised that I could just get all of the terms (in one go!) and use their ‘path’ properties to determine if they’re a child or not. Node B is a child of A if B’s path starts with A’s path. Great, so I can determine child nodes – now the next issue. The Terms have IDs that are GUIDs. The CAML query uses integer IDs that look up onto the hidden ‘TaxonomyHiddenList’. This is what it sounds like – a hidden list that stores taxonomy terms for the Site Collection, and is used as a lookup list by taxonomy columns. Therefore, I need to resolve the integer IDs for the terms, based on their GUIDs, within this list. That’s just another query, but that’s fairly straight forward. Finally, once I’ve got all the integer IDs, I can get the list items that use IDs in that set. Phew! That’s a lot, and the early parts – regarding the taxonomy – are much more complicated than it really should be. The code I ended up with was:

var term;
var terms;
var termGUIDs = new Array();
var termIDs = new Array();

function execGetTerms(){
  termGUIDs = new Array();
  termIDs = new Array();
  var context = SP.ClientContext.get_current();
  //Current Taxonomy Session
  var taxSession = SP.Taxonomy.TaxonomySession.getTaxonomySession(context);
  //Term Stores
  var termStores = taxSession.get_termStores();
  //Name of the Term Store from which to get the Terms.
  var termStore = termStores.getByName('Taxonomy_xgJ9gi6IRQkd7J4FOMuhMw==');
  //GUID of Term Set from which to get the Terms.
  var termSet = termStore.getTermSet('0243a547-bcad-49e8-a8e9-4f6ebe7b8185');
  term = termSet.getTerm('cdf106e5-84af-44db-8419-dbff5a221ebc');
  terms = termSet.getAllTerms();
  context.load(term);
  context.load(terms);
  context.executeQueryAsync(
	Function.createDelegate(this, getTermsComplete),
	function(sender,args){ alert( 'Get Terms: ' + args.get_message());}
	);
}
function getTermsComplete()
{
	var html = '<ul>';
	var termEnumerator = terms.getEnumerator();
	var termPath = term.get_pathOfTerm();
	//For each term, find out if it is a child of the term we've selected.
	//Use the path as 'getIsDescentantOf' method always seems to return true.
	//http://msdn.microsoft.com/en-us/library/office/apps/dn312621.aspx
    while(termEnumerator.moveNext()){
      var currentTerm = termEnumerator.get_current();
	  var currentTermPath = currentTerm.get_pathOfTerm();

	  if(currentTermPath.indexOf(termPath) == 0){
	    html+='<li>' + currentTerm.get_name() + ' [' + currentTerm.get_pathOfTerm() + ']</li>';
		termGUIDs.push(currentTerm.get_id().toString());
	  }
    }
	html+='</ul>';
	//Output interim details of what terms are this node or subnodes
	var div = document.getElementById('outputDiv').innerHTML = html;
	execGetTermIDs();
}
function execGetTermIDs(){
  //We've got the Term GUIDs, but need the integer IDs.
  //Look them up on the hidden taxonomy list.
  var q = '<View><Query><Where><In><FieldRef Name='IdForTerm'/><Values>';
  for (var i = 0; i < termGUIDs.length; i++) {
	q+='<Value Type='Text'>' + termGUIDs[i] + '</Value>';
  }
  q+='</Values></In></Where></Query></View>';
  var context = SP.ClientContext.get_current();
  //Query the hidden taxonomy list!
  var oList = context.get_web().get_lists().getByTitle('TaxonomyHiddenList');
  var camlQuery = new SP.CamlQuery();
  camlQuery.set_viewXml( q );
  this.collTermListItem = oList.getItems(camlQuery);
  context.load(collTermListItem);
  context.executeQueryAsync(
	Function.createDelegate(this, getTermIDsComplete),
	function(sender,args){ alert( 'Get Term IDs: ' + args.get_message());}
	);
}
function getTermIDsComplete()
{
	//Got the IDs, create a set of them.
	var listItemEnumerator = collTermListItem.getEnumerator();
    while (listItemEnumerator.moveNext()) {
        var oListItem = listItemEnumerator.get_current();
		termIDs.push(oListItem.get_id());
    }
	execGetListItems();
}
function execGetListItems(){
  //Now query the list using the set of integer IDs from the hidden list.
  var q = '<View><Query><Where><In><FieldRef Name='Term' LookupId='true' /><Values>';
  for (var i = 0; i < termIDs.length; i++) {
	q+='<Value Type='Lookup'>' + termIDs[i] + '</Value>';
  }
  q+='</Values></In></Where><OrderBy><FieldRef Name='Term' /></OrderBy></Query></View>';
  var context = SP.ClientContext.get_current();
  var oList = context.get_web().get_lists().getByTitle('CustomListA');
  var camlQuery = new SP.CamlQuery();
  camlQuery.set_viewXml( q );

  this.collListItem = oList.getItems(camlQuery);
  context.load(collListItem);
  context.executeQueryAsync(
	Function.createDelegate(this, getListItemsComplete),
	function(sender,args){ alert( 'Get List Items: ' + args.get_message());}
	);

}
function getListItemsComplete() {
	var html = '<ul>';
    var listItemEnumerator = collListItem.getEnumerator();
    // Do something about displaying them.
    while (listItemEnumerator.moveNext()) {
        var oListItem = listItemEnumerator.get_current();
        html += '<li>' + oListItem.get_id() + ': ' + oListItem.get_item('Title') + ' - ' + oListItem.get_item('Term').get_label() + '</li>';
    }
	html += '</ul>';
	var div = document.getElementById('outputDiv').innerHTML = html;
}

And this worked! Note that the code is hard coded with Taxonomy service, term set and starting term IDs.

Advertisements
Using JSOM to query SharePoint 2013 lists with Taxonomy Fields

6 thoughts on “Using JSOM to query SharePoint 2013 lists with Taxonomy Fields

  1. Stephanie says:

    Hi! I have tried to do this all day! And I just found your blog! Perfect! But I have one problem with the code, I don’t understand all the “html+=&quot;&lt;/ul&gt;&quot;;. Do you have the code with the “real” charactes so I know that to write? It’s in every method you have.
    Please get back to me. I would appreciate it so much!

    Like

    1. Stephanie says:

      Thank you! I get all the labels out on the screen now. But I can’t see any items from the list.

      But I get an alert error. It can’t find the TaxonomyHiddenList. Do I need to do something? Is it called something else?
      //Query the hidden taxonomy list!
      var oList = context.get_web().get_lists().getByTitle(‘TaxonomyHiddenList’.

      And what do you mean by IdForTerm? Should I just write in the ID?
      //Look them up on the hidden taxonomy list.
      var q = ”;

      And by Term you mean that I sould write in the name of the term? Or the manage metadata column name? Or is it supposed to say Term?
      //Now query the list using the set of integer IDs from the hidden list.
      var q = ”;
      and:
      q+=”;
      var context = SP.ClientContext.get_current();

      Like

  2. Stephanie says:

    The code wouldn’t post, haha. Oh, I sound so stupid right now. I figured out what you meant on the other 2 questions. But I still get the error for:
    But I get an alert error. It can’t find the TaxonomyHiddenList. Do I need to do something? Is it called something else?
    //Query the hidden taxonomy list!
    var oList = context.get_web().get_lists().getByTitle(‘TaxonomyHiddenList’.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s