HomeAbout Me
Microsoft 365
Update managed metadata fields with PnPJs
Simon Ågren
Simon Ågren
November 09, 2018
1 min
Update managed metadata fields with PnPJs

Last night I was helping out with an issue in the PnPJs repository on GitHub where the user wanted to update a managed metadata column. I love PnPJs because it makes difficult rest calls really simple and intuitive to execute. The user was still hoping for a more simple solution than what I provided - and I don’t blame him.

So I made a few methods where the user can send in a term och terms, directly from the termset. So we will be able to update both multi and single valued managed metadata columns quite easily.

Updating a single valued

Here we send in a term (with types from PnPJs), the list name, the field name, and the Id of the item we wish to update.

We are using -1 as WssId and that’s fine, it will sort it self automatically. After setting up the data object we use PnPJs to update the item, and return the updated item data.

public async updateMeta(term: (ITerm & ITermData), listName: string, fieldName: string, itemId: number): Promise<any> {
const data = {};
data[fieldName] = {
"__metadata": { "type": "SP.Taxonomy.TaxonomyFieldValue" },
"Label": term.Name,
'TermGuid': this.cleanGuid(term.Id), // field guid
'WssId': '-1' // fake
};
return await sp.web.lists.getByTitle(listName).items.getById(itemId).update(data);
}

Updating a multi valued

Here we send in multiple terms (with types from PnPJs), the list name, the field name, and the Id of the item we wish to update.

Here are we concatinating all the values in to one single string. Here we are also using -1 as WssId, the name and the Id of the Term.

We do an additional call to get the hidden field that’s related to the metadata field, then we use the internalname in the data object.

Then we update the item with PnPJs in the same way as before. The real difference is just the data object in these cases.

public async updateMultiMeta(terms: (ITerm & ITermData)[], listName: string, fieldName: string, itemId: number): Promise<any> {
const data = {};
const list = await sp.web.lists.getByTitle(listName);
const field = await list.fields.getByTitle(`${fieldName}_0`).get();
let termsString: string = '';
terms.forEach(term => {
termsString += `-1;#${term.Name}|${this.cleanGuid(term.Id)};#`;
})
data[field.InternalName] = termsString;
return await list.items.getById(itemId).update(data);
}

The full code

This is not being used in production, you might have to tweak the code to some extent.

import { sp } from "@pnp/sp";
import { taxonomy, ITerm, ITermData } from "@pnp/sp-taxonomy";
public async doStuff(): Promise<void> {
// Using taxonomy to get term set
const store = await taxonomy.getDefaultSiteCollectionTermStore();
const termset = await store.getTermSetById("10e3b8d1-edef-48ce-82f4-d184c5cd49b2");
// get a single term
const term = await termset.terms.getByName("Term2").get();
// get all terms in termset
const terms = await termset.terms.get();
// Update single valued taxonomy field and log updated item
console.log(await this.updateMeta(term, 'ListName', 'Meta', 1));
// Update multi valued taxonomy field and log updated item
console.log(await this.updateMultiMeta(terms, 'ListName', 'MultiMeta', 1));
}
public cleanGuid(guid: string): string {
if (guid !== undefined) {
return guid.replace('/Guid(', '').replace('/', '').replace(')', '');
} else {
return '';
}
}
public async updateMeta(term: (ITerm & ITermData), list: string, field: string, itemId: number): Promise<any> {
const data = {};
data[field] = {
"__metadata": { "type": "SP.Taxonomy.TaxonomyFieldValue" },
"Label": term.Name,
'TermGuid': this.cleanGuid(term.Id),
'WssId': '-1'
};
return await sp.web.lists.getByTitle(list).items.getById(itemId).update(data);
}
public async updateMultiMeta(terms: (ITerm & ITermData)[], listName: string, fieldName: string, itemId: number): Promise<any> {
const data = {};
const list = await sp.web.lists.getByTitle(listName);
const field = await list.fields.getByTitle(`${fieldName}_0`).get();
let termsString: string = '';
terms.forEach(term => {
termsString += `-1;#${term.Name}|${this.cleanGuid(term.Id)};#`;
})
data[field.InternalName] = termsString;
return await list.items.getById(itemId).update(data);
}

Tags

sharepointpnp
Previous Article
Create a Microsoft Team using site designs, Flow and Hub Sites

Simon Ågren

CTA & Microsoft MVP

Solving business problems with tech

Expertise

Microsoft 365
Azure

Social Media

githubtwitterwebsite

Related Posts

Groupify a SharePoint site - the collection
Groupify a SharePoint site - the collection
September 10, 2022
2 min

Quick Links

About

Social Media