Share and Enjoy !

So I learned a really cool taxonomy trick the other day when I needed to be able to update both single select and multi-select Managed Metadata fields via JavaScript and REST. For one of our clients, I have a custom action button that copies a document from a root site document library to a subsite document library, complicated further by having multiple content types and lots of Managed Metadata to contend with while copying.

While adding yet another content type and more fields to the function, I found that my current code, where I was using a GetItems AJAX call to return my data, wouldn’t do the trick for some of my new fields. That’s when I ran across this nifty article – http://sympmarc.com/2017/06/19/retrieving-multiple-sharepoint-managed-metadata-columns-via-rest/ – that explained how to use a field called TaxCatchAll to bring back what I needed. The TaxCatchAll data is actually held in a hidden SharePoint list called TaxonomyHiddenList and can be accessed via this link:

<site collection URL>/Lists/TaxonomyHiddenList/AllItems.aspx

When added to your REST call and expanded, it will bring back all the data you need though it does need a little massaging.

NOTE: One problem I encountered when I started using the TaxCatchAll field was that my users did not have the correct permissions to pull this information and so the copy process was hanging up and throwing a 401 unauthorized error. This is because the TaxonomyHiddenList list has unique permissions and sometimes they just aren’t set up correctly, which was my case. In order for my copy process to work correctly, I had to go in and grant my users read access to the list. After that, all proceeded as planned.

Here’s an example REST call for pulling the data. Notice that you have to expand the TaxCatchAll fields in order to get all the information you need. The changes I had to make to my REST call involved swapping from a ‘GetItems’ query to a ‘select’ call so that I could pull back the extra taxonomy data.

_spPageContextInfo.webAbsoluteUrl +    "/_api/lists/getbyTitle('DocumentLibrary')/items?" +         "$select= MetaSingleField, MetaMultiField " + "TaxCatchAll/ID,TaxCatchAll/Term&$expand=TaxCatchAll&$filter=ID eq " + itemData.itemId

For the TaxCatchAll field, you see that it includes all the pertinent data for your taxonomy field and all in the correct places. Go, team! Now we just need to find a way to match it up to the actual Managed Metadata field value.Here is what the all the metadata looks like when returned. Note that for a single value Managed Metadata field, the actual label text value is not returned to you. Instead, it looks like they put the WssId value in the Label field, which is not at all helpful. If you look at the data returned for a multi-select field though, you’ll see it pulls the Label value correctly. Very weird.

" MetaSingleField ": {

"__metadata": {

"type": "SP.Taxonomy.TaxonomyFieldValue"

},

“Label": "1289",

"TermGuid": "0b032022-d156-49eb-9a48-904df5411349",

"WssId": 1289

}

" MetaMultiField ": {

"__metadata": {

"type": "Collection(SP.Taxonomy.TaxonomyFieldValue)"

},

"results": [

{

"Label": " Label ABC",

"TermGuid": "158a84f4-e5ff-440b-b55f-d30b0f77c402",

"WssId": 1291

},

{

"Label": " Label DEF",

"TermGuid": "03d2d388-a863-4f5d-818d-d71d948f763d",

"WssId": 1290

}

]

}

"TaxCatchAll": {

"results": [

{

"__metadata": {

"id": "158a84f4-e5ff-440b-b55f-d30b0f77c402",

"type": "SP.Data.TaxonomyHiddenListListItem"

},

"ID": 1291,

"Term": "Label ABC"

},

{

"__metadata": {

"id": "03d2d388-a863-4f5d-818d-d71d948f763d",

"type": "SP.Data.TaxonomyHiddenListListItem"

},

"ID": 1290,

"Term": "Label DEF"

},

{

"__metadata": {

"id": "0b032022-d156-49eb-9a48-904df5411349",

"type": "SP.Data.TaxonomyHiddenListListItem"

},

"ID": 1289,

"Term": "Label XYZ"

}

]

}

That’s where Marc Anderson’s nifty script came in to do that job for us. All I had to do was tweak it a little bit in order to meet my particular needs. One thing to note is that this only handles single value taxonomy fields. When pulling a multi-select Managed Metadata field, we already have what we need in the results, so we just need to parse those instead of using the TaxCatchAll data. For reference, I’ve included the multi-value function at the bottom of this article as well.

Here’s how you call my version of the single value script:

getTaxonomyValue(results, ” MetaSingleField”, “labelOnly”)

results = results of your REST call
fieldname = name of metadata field
“labelOnly” = a static string that will tell the function to only return the text value of the field.

function getTaxonomyValue(obj, fieldName, returnValue) {

// Below function pulled from here and tweaked to work as I needed it.

// https://sympmarc.com/2017/06/19/retrieving-multiple-sharepoint-managed-metadata-columns-via-rest/

//

// Use this function to pull values from single select managed metadata fields

//

// To return only the text value (label) of the managed metadata field, pass in a returnValue of 'labelOnly'; otherwise pass in nothing

// and a properly formatted string will be returned that can be used to update a managed metadata field.

//

var metaString = "";

// Iterate over the fields in the row of data

for (var field in obj) {

// If it's the field we're interested in....

if (obj.hasOwnProperty(field) &amp;&amp; field === fieldName) {

if (obj[field] !== null) {

// ... get the WssId from the field ...

var thisId = obj[field].WssId;

// ... and loop through the TaxCatchAll data to find the matching Term

for (var i = 0; i < obj.TaxCatchAll.results.length; i++) {

if (obj.TaxCatchAll.results[i].ID === thisId) {

// Only return the text value

if (returnValue && returnValue === "labelOnly") {

metaString = obj.TaxCatchAll.results[i].Term;

break;

}

else {

// Return a formatted value that can be used to update managed metadata values

metaString = thisId + ";#" + obj.TaxCatchAll.results[i].Term + "|" + obj[field].TermGuid;

break;

}

}

}

}

}

}

// No luck, so return empty string

return metaString;

}

I modified it so that it could return either the straight text label or a formatted value that can be used to update a Managed Metadata field. It all works like a charm!

And as promised above, here’s the function I call for parsing out multi-select Managed Metadata values.

parseManagedMetadata (results, " MetaMultiField")

results = results of your REST call
fieldname = name of metadata field

function parseManagedMetadata(results, fieldName) {

// Build out the managed metadata string needed for later updating.

// Some links that helped me figure all this out.

// http://www.aerieconsulting.com/blog/using-rest-to-update-a-managed-metadata-column-in-sharepoint

// http://www.aerieconsulting.com/blog/update-using-rest-to-update-a-multi-value-taxonomy-field-in-sharepoint

// http://stackoverflow.com/questions/17076509/set-taxonomy-field-multiple-values

// Use this function to pull values from multivalue managed metadata fields. Technically it will return single select labels also, but

// that will depend on the rest call used.

// First try to pull out a basic label value. If not found then it's probably a multivalue field.

var labelValue = parseValue(results, fieldName);

if (labelValue == "" && results[fieldName].results == undefined) {

return {};

}

var metaString = "";

var metaSeparator = "";

if (labelValue != "") {

// We have a single value field

metaString = results[fieldName].WssId + ";#"+ labelValue + "|" + results[fieldName].TermGuid;

}

else {

// We have a multivalue field

var fieldValues = results[fieldName].results;

for (var i = 0; i < fieldValues.length; i++) {

metaString += metaSeparator + fieldValues[i].WssId + ";#" + fieldValues[i].Label + "|" + fieldValues[i].TermGuid;

metaSeparator = ";#";

}

}

return metaString;

}

I hope this helps someone!

Share and Enjoy !

Related Content: