-
-
Notifications
You must be signed in to change notification settings - Fork 58
Retrieve Term Set
It can be a bit tricky to retrieve a Term Set. Hopefully, SharepointPlus (from v4.1) can help you.
After you have created your term set, and after you have added a Managed Metadata column into your list, you'll be able to retrieve the properties for the term set defined for your Managed Metadata column.
To do so, you need to get the info for your list. Below is an example with a list called My_List and a Managed Metadata column called Tags:
var taxonomyConfiguration = {sspId:"", termSetId:""};
$SP().list("My_List").info(function(fields) {
for (var i=0; i<fields.length; i++) {
if (fields[i]["DisplayName"] === "Tags") {
console.log("sspId => ",fields[i].Property.SspId);
console.log("termSetId => ",fields[i].Property.TermSetId);
taxonomyConfiguration.sspId = fields[i].Property.SspId;
taxonomyConfiguration.termSetId = fields[i].Property.TermSetId;
}
}
});
We have three solutions.
Now that you have sspId (note the 'I' in upper case) and termSetId, you can get the term set properties.
While retrieving the XML from the server, you'll find some unobvious names for properties. Here some tips:
Property
a9
is thetermId
Propertya32
is thetermName
Propertya25
is theparentTermId
Propertya69
istrue
when there are children
Below is the valid code (using Promise
) that will return all your terms in your set:
function getAllTerms() {
$SP().webService({
service:"TaxonomyClientService",
operation:"GetChildTermsInTermSet",
webURL:"https://my.website.com",
soapURL:"http://schemas.microsoft.com/sharepoint/taxonomy/soap/",
properties:{
sspId:taxonomyConfiguration.sspId,
lcid:1033,
termSetId:taxonomyConfiguration.termSetId
}
}).then(function(data) {
return parseTermXML(data.querySelector('GetChildTermsInTermSetResult'))
})
}
// data is the content returned by the server
function parseTermXML(data) {
return new Promise(function(resolve, reject) {
var domParser, xml, t, i, terms=[];
// parse the result to XML
domParser = new window.DOMParser();
xml = data.firstChild.nodeValue;
xml = domParser.parseFromString(xml, "text/xml");
t = xml.querySelectorAll('T');
if (t.length === 0) resolve(terms);
else {
for (i=0; i<t.length; i++) {
terms.push({
Name:t[i].querySelector('TL').getAttribute("a32"),
ID:t[i].getAttribute("a9"),
Children:(t[i].querySelector('TM').getAttribute("a69") == "true" ? [] : null)
});
}
// if we have children, then we find them
var dfd = Promise.resolve();
var res = terms.map(function(term) {
dfd = dfd.then(function() {
if (term.Children === null) {
term.Children=[];
return Promise.resolve(term);
} else {
return getTerm(term).then(function(children) {
term.Children = children;
return Promise.resolve(term);
})
}
});
return dfd
});
Promise.all(res).then(function(terms) {
resolve(terms)
})
}
})
}
// get sub terms
function getTerm(term) {
return $SP().webService({
service:"TaxonomyClientService",
operation:"GetChildTermsInTerm",
webURL:"https://my.website.com",
soapURL:"http://schemas.microsoft.com/sharepoint/taxonomy/soap/",
properties:{
sspId:taxonomyConfiguration.sspId,
lcid:1033,
termSetId:taxonomyConfiguration.termSetId,
termId:term.ID
}
}).then(function(data) {
return parseTermXML(data.querySelector('GetChildTermsInTermResult'))
})
}
getAllTerms().then(function(terms) {
console.log("All the terms => ",terms)
})
The downside with using SOAP Web Service is we need to do one request by group of terms. So depending how big is your term store, it will become too much heavy.
On this blog post you can have an interesting method to get terms from JSON, or from Stackoverflow too. It's faster because it permits to retrieve all the terms with 2 requests (one for context/digest and one for the terms).
(my favorite one because it will use far less code and requests than from the other 2 solutions)
I don't like JSOM, especially because I don't necessary want to load all the crapy Sharepoint Javascript files. So we can simply simulate the AJAX request that is sent and parse the result.
The full code for SharepointPlus 4.1:
var siteurl="https://my.website.com";
function getAllTerms(termSetId) {
return new Promise(function(resolve, reject) {
// retrieve context info for FormDigestValue
$SP().ajax({
method:'POST',
url:siteurl+'/_api/contextinfo',
beforeSend: function(xhr) { xhr.setRequestHeader('Accept', 'application/json;odata=verbose'); },
success:function(data) {
resolve(data)
}
})
}).then(function(data) {
var requestdigest=(typeof data === "string" ? JSON.parse(data) : data).d.GetContextWebInformation.FormDigestValue;
// retrieve terms by simulating the request sent with JSOM
return new Promise(function(prom_resolve, prom_reject) {
var data = '<Request xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009" SchemaVersion="15.0.0.0" LibraryVersion="15.0.0.0" ApplicationName="Javascript Library"><Actions><ObjectPath Id="149" ObjectPathId="148" /><ObjectIdentityQuery Id="150" ObjectPathId="148" /><ObjectPath Id="152" ObjectPathId="151" /><ObjectIdentityQuery Id="153" ObjectPathId="151" /><ObjectPath Id="155" ObjectPathId="154" /><ObjectIdentityQuery Id="156" ObjectPathId="154" /><ObjectPath Id="158" ObjectPathId="157" /><Query Id="159" ObjectPathId="157"><Query SelectAllProperties="true"><Properties /></Query><ChildItemQuery SelectAllProperties="true"><Properties /></ChildItemQuery></Query></Actions><ObjectPaths><StaticMethod Id="148" Name="GetTaxonomySession" TypeId="{981cbc68-9edc-4f8d-872f-71146fcbb84f}" /><Method Id="151" ParentId="148" Name="GetDefaultSiteCollectionTermStore" /><Method Id="154" ParentId="151" Name="GetTermSet"><Parameters><Parameter Type="String">'+termSetId+'</Parameter></Parameters></Method><Method Id="157" ParentId="154" Name="GetAllTerms" /></ObjectPaths></Request>';
$SP().ajax({
method:'POST',
url:siteurl+'/_vti_bin/client.svc/ProcessQuery',
beforeSend: function(xhr) { xhr.setRequestHeader('X-RequestDigest', requestdigest) },
data:data,
success:function(response) {
prom_resolve(response);
},
error:function(err) {
prom_reject()
}
})
})
}).then(function(response) {
return new Promise(function(prom_resolve, prom_reject) {
var terms=[]
response.forEach(function(obj) {
if (obj._ObjectType_ && obj._ObjectType_==="SP.Taxonomy.TermCollection") {
obj._Child_Items_.forEach(function(term) {
terms.push(term)
})
}
});
// sort based on path
terms.sort(function(a,b) {
if (a.PathOfTerm < b.PathOfTerm) return -1;
if (a.PathOfTerm > b.PathOfTerm) return 1;
return 0
})
prom_resolve(terms)
})
})
}
getAllTerms(taxonomyConfiguration.termSetId).then(function(terms) {
console.log(terms) // 'terms' is a nice array with all the properties returned for the terms
})
And the same thing but with SharepointPlus 5.0+:
var siteurl="https://my.website.com";
function getAllTerms(termSetId) {
// retrieve terms by simulating the request sent with JSOM
var data = '<Request xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009" SchemaVersion="15.0.0.0" LibraryVersion="15.0.0.0" ApplicationName="Javascript Library"><Actions><ObjectPath Id="149" ObjectPathId="148" /><ObjectIdentityQuery Id="150" ObjectPathId="148" /><ObjectPath Id="152" ObjectPathId="151" /><ObjectIdentityQuery Id="153" ObjectPathId="151" /><ObjectPath Id="155" ObjectPathId="154" /><ObjectIdentityQuery Id="156" ObjectPathId="154" /><ObjectPath Id="158" ObjectPathId="157" /><Query Id="159" ObjectPathId="157"><Query SelectAllProperties="true"><Properties /></Query><ChildItemQuery SelectAllProperties="true"><Properties /></ChildItemQuery></Query></Actions><ObjectPaths><StaticMethod Id="148" Name="GetTaxonomySession" TypeId="{981cbc68-9edc-4f8d-872f-71146fcbb84f}" /><Method Id="151" ParentId="148" Name="GetDefaultSiteCollectionTermStore" /><Method Id="154" ParentId="151" Name="GetTermSet"><Parameters><Parameter Type="String">'+termSetId+'</Parameter></Parameters></Method><Method Id="157" ParentId="154" Name="GetAllTerms" /></ObjectPaths></Request>';
return $SP().ajax({
body:data,
url:siteurl+'/_vti_bin/client.svc/ProcessQuery'
}).then(function(response) {
var terms=[];
response.forEach(function(obj) {
if (obj._ObjectType_ && obj._ObjectType_==="SP.Taxonomy.TermCollection") {
obj._Child_Items_.forEach(function(term) {
terms.push(term)
})
}
});
// sort based on path
terms.sort(function(a,b) {
if (a.PathOfTerm < b.PathOfTerm) return -1;
if (a.PathOfTerm > b.PathOfTerm) return 1;
return 0
})
return Promise.resolve(terms)
})
}
getAllTerms(taxonomyConfiguration.termSetId).then(function(terms) {
console.log(terms)
})
So we needed 2 requests only (one to get context/digest and one to get all the terms), and without loading sp.taxonomy.js
or even sp.js
.