Technology•Apr 19, 2017
Editing Multi-Value Managed Metadata Fields With JavaScript in SharePoint Online
One of the use cases for a recent SharePoint Online (SPO) project required leveraging the JavaScript object model (JSOM) to add or remove managed metadata terms on a list item field. Considering that setting the value for a single-value managed metadata field is fairly straightforward, this task turned out to be slightly trickier than I originally anticipated. This post explains how to add an additional term to the list item field value, as well as how to remove one.
Environment Setup and Assumptions
Let’s assume that our SPO environment consists of the following:
A term set within the default tenant term store called “Skills”.
A site with a relative path of “/sites/employees”.
A custom content type called “Employee” that includes a field called “Skills”, which is configured as a managed metadata column that uses the “Skills” term set and allows multiple values.
A list called “Employee List” that has been configured so the only available content type is “Employee”.
An item in the list with the title “John Doe”.
The list item ID is 1.
The Skills field for this list item currently has two terms, with the labels JavaScript and Ruby.
Adding New Terms to the Field Value
In order to edit the existing contents of a multi-value field, you’ll need to set a TaxonomyFieldValueCollection object with the appropriate terms. The simplest way to do this is to form a string that contains the GUID, WSS ID, and Label of each term that should be included in the collection, and then convert this string into the TaxonomyFieldValueCollection.
The string should use the following format: WssId;#Label|GUID, with “;#” used as the delimiter. For example, suppose you have the following terms:
Term 1: LabelJavaScriptWSS ID23GUID725abddc-37d1-4675-3364-a9da0020cd1c
Term 2: LabelRubyWSS ID24GUID932dacbd-66d4-2150-5312-b3ac1482ac5d
A TaxonomyFieldValueCollection that includes both of these terms would be represented by the following string: "23;#JavaScript|725abddc-37d1-4675-3364-a9da0020cd1c;#24;#Ruby|932dacbd-66d4-2150-5312-b3ac1482ac5d"
The JavaScript snippet below shows how to add a new term to a managed metadata list item field:
function addTermToFieldValue(
termGuidToAdd, //GUID of the term to add to the collection
termLabelToAdd, //Label of the term to add to the collection
siteUrl, //Relative URL of the relevant site
listName, //Title of the relevant list
listItemId, //ID of the relevant list item
fieldName) //Internal name of the multi-value managed metadata field
{
//Code requires sp.js and sp.taxonomy.js
SP.SOD.loadMultiple(['sp.js', 'sp.taxonomy.js'], function () {
//Instantiate the client context
var ctx = new SP.ClientContext(siteUrl);
//Load the list item
var oList = ctx.get_web().get_lists().getByTitle(listName);
self.oListItem = oList.getItemById(listItemId);
ctx.load(self.oListItem);
//Load the managed metadata site column
var field = oList.get_fields().getByInternalNameOrTitle(fieldName);
self.txField = ctx.castTo(field, SP.Taxonomy.TaxonomyField);
ctx.load(self.txField);
//Run query
ctx.executeQueryAsync(function () {
//Get the managed metadata field on the list item
var listField = self.oListItem.get_item(fieldName);
var enumerator = listField.getEnumerator();
//Define variable to contain the string of terms for the field value
var termStr = "";
//Iterate through current terms within the field
while (enumerator.moveNext()) {
var item = enumerator.get_current();
var guid = item.get_termGuid();
var wssId = item.get_wssId();
var label = item.get_label();
termStr += wssId + ';#' + label + '|' + guid + ';#';
}
//Add new term to the string. Use -1 for WssId.
termStr += "-1;#" + termLabelToAdd + "|" + termGuidToAdd;
//Convert the term string to a TaxonomyFieldValueCollection
var newTerms = new SP.Taxonomy.TaxonomyFieldValueCollection(ctx, termStr, self.txField);
//Set the field value to the new TaxonomyFieldValueCollection
self.txField.setFieldValueByValueCollection(self.oListItem, newTerms);
//Update the list item
self.oListItem.update();
ctx.load(self.oListItem);
//Run query
ctx.executeQueryAsync(function () {
//Success
console.log('Field successfully updated.');
}, function (sender, args) {
//Error
console.log('An error occurred:' + args.get_message());
});
});
});
}
Using the environment setup we defined above, you could then call the following in order to add the term “Python” to the Skills field for John Doe (note: Python is assumed to be an existing term in the term set with an existing GUID, it just isn’t on this particular list item field):
var guidToAdd = "00000000-0000-0000-000000000000"; //real GUID goes herevar labelToAdd = "Python";
var siteUrl = "https://<domain>.sharepoint.com/sites/employees";var listName = "Employee List";
var listItemId = 1; //ID for John Doevar fieldName = "Skills";
addTermToFieldValue(guidToAdd, labelToAdd, siteUrl, listName, listItemId, fieldName);
A few important notes:
The script uses the SOD.loadMultiple
method to ensure the dependencies for the logic (sp.js and sp.taxonomy.js) are loaded.
After the existing terms in the current field value are loaded, the script iterates through the collection to form the appropriate string.
The script then adds the new term using the specified termLabelToAdd and termGuidToAdd, with a WSS ID of -1 (the WSS ID will change once the specified term is added to the field value).
Once the new term has been added to the string, it’s converted into a TaxonomyFieldValueCollection variable, which will be used to actually set the new value for the field.
Removing Terms From the Field Value
The process to remove a term is very similar. You’ll still need to iterate through all the existing terms within the field value to form the appropriate string—but if the GUID of a term equals the GUID of the term needing to be removed, then you simply won’t include that term in the string that’s being built.
The following shows the full implementation:
function removeTermFromFieldValue(
termGuidToRemove,
siteUrl,
listName,
listItemId,
fieldName) {
//Code requires sp.js and sp.taxonomy.js
SP.SOD.loadMultiple(['sp.js', 'sp.taxonomy.js'], function () {
//Instantiate the client context
var ctx = new SP.ClientContext(siteUrl);
//Load the list item
var oList = ctx.get_web().get_lists().getByTitle(listName);
self.oListItem = oList.getItemById(listItemId);
ctx.load(self.oListItem);
//Load the managed metadata site column
var field = oList.get_fields().getByInternalNameOrTitle(fieldName);
self.txField = ctx.castTo(field, SP.Taxonomy.TaxonomyField);
ctx.load(self.txField);
//Run query
ctx.executeQueryAsync(function () {
//Get the managed metadata field on the list item
var listField = self.oListItem.get_item(fieldName);
var enumerator = listField.getEnumerator();
//Define variable to contain the string of terms for the field value
var termStr = "";
//Iterate through current terms within the field
while (enumerator.moveNext()) {
var item = enumerator.get_current();
var guid = item.get_termGuid();
//As long as the GUID of the current item doesn't match the
//GUID of the one to remove, add it to the term string
if (guid != termGuidToRemove) {
var guid = item.get_termGuid();
var wssId = item.get_wssId();
var label = item.get_label();
termStr += wssId + ';#' + label + '|' + guid + ';#';
}
}
//Remove the trailing ";#" characters
termStr = termStr.slice(0,-2);
//Convert the term string to a TaxonomyFieldValueCollection
var newTerms = new SP.Taxonomy.TaxonomyFieldValueCollection(ctx, termStr, self.txField);
//Set the field value to the new TaxonomyFieldValueCollection
self.txField.setFieldValueByValueCollection(self.oListItem, newTerms);
//Update the list item
self.oListItem.update();
ctx.load(self.oListItem);
//Run query
ctx.executeQueryAsync(function () {
//Success
console.log('Field successfully updated.');
}, function (sender, args) {
//Error
console.log('An error occurred:' + args.get_message());
});
});
});
}
And going back to the “John Doe” example, you could call this method as follows if you wanted to remove “Ruby” from the Skills field:
var guidToRemove = "932dacbd-66d4-2150-5312-b3ac1482ac5d"; //GUID for Rubyvar siteUrl = "https://<domain>.sharepoint.com/sites/employees";
var listName = "Employee List";
var listItemId = 1; //ID for John Doevar fieldName = "Skills";
removeTermFromFieldValue(guidToRemove, siteUrl, listName, listItemId, fieldName);
A few important notes:
As mentioned before, the while loop now contains a conditional statement so that the term with the GUID to be removed will
not
be added into the string that represents the new value.
The line
termStr = termStr.slice(0,-2)
; is used simply to remove the trailing “;#” that would be included at the end of the string after exiting the while loop.
Conclusion
If you have questions or comments about this blog post or other aspects of SharePoint Online development, contact us at findoutmore@credera.com.