
Display hierarchical Term Sets to your Web Part
You have a SharePoint list or a documents library in which you management the content by managed metadata; you want to display the content of this list in accordance with a selected path chosen by the users. Natively, without additional feature to the site or list, you can use:
- The column header, directly from the list view


- With the new experience, the filter panel

However, you have no native Web Part that allows you to display a custom path selector.
Ok, but what for? Image you wish provide a documentation about tools in accordance with a use case. The users follow the path of use case and at the end, they should find all documents in accordance with them path. Like that:

Once the Term is retrieved, it is possible to display the result in accordance with this one.
Below, the solution I have chosen:
Get Taxonomy
PnPjs π³ to retrieve a Term Sets of current site based on a field from list:
sp.web.lists.getById('00000000-0000-0000-0000-000000000000').fields.getById('11111111-1111-1111-1111-111111111111').get().then((field) => {
taxonomy.getDefaultSiteCollectionTermStore().getTermSetById(field.TermSetId).terms.get().then((t) => {
console.log(t); /* HERE ALL TERMS FROM TERM SETS */
});
});
The result is π π:

Transfom data
Now, transform this result to an object that can be reused to display a tree. I chose the structure proposed by the framework jsTree.
First, create a function that allows to get each individual term:
public buildTree(ts: Array<any>): Array<any> {
var tree = [];
ts.forEach(term => {
tree = this.branch(tree, term)
});
return tree;
}
buildTree()
use the most important recursive function named branch()
that allows to reproduce the hierarchy:
private branch(tree: Array<any>, term: any, node: any = null, i: number = 0): Array<any> {
var pathOfTerm = term.PathOfTerm.split(';');
/* Switch level */
var c = node == null ? tree : node;
if (i < pathOfTerm.length) { /* Ensure not loop recursive */
var r = c.find(function (obj) { return obj.text === pathOfTerm[i]; }); /* check if node already exist */
if (r) { /* If exist */
if ((i + 1) == pathOfTerm.length) { /* Update ID if node == current term */
r.id = term.Id.replace('/Guid(', '').replace(')/', '');
} else { /* recursive children */
this.branch(tree, term, r.children, i + 1);
}
} else { /* Not exists, create new node */
/* See : https://www.jstree.com/docs/json/ for all specification */
var o = { "text": pathOfTerm[i], "id": null, "state": { "opened": false }, "children": [] };
if ((i + 1) == pathOfTerm.length) { /* If it's a root node or last child, set ID */
o.id = term.Id.replace('/Guid(', '').replace(')/', '');
} else { /* recursive children */
this.branch(tree, term, o.children, i + 1);
}
c.push(o);
}
}
return c;
}
In this function, the following rows allow to define the template of each node :
var o = { "text": pathOfTerm[i], "id": null, "state": { "opened": false }, "children": [] };
o.id = term.Id.replace('/Guid(', '').replace(')/', '');
And here the result of the object model πͺπ» :

With this kind of data object, you can directly use the jsTree render or create your own HTML structure like that :

Get the selected (clicked) Term
Now, you probably want get which term was selected, update the view and do something else...
To do this, add an `addEventListener()` on your render tree nodes (in my case, I'm using the CSS class `termSelector`) and attach the click event to the following function that return the object node selected :
public toggleSelectedTerm(tree: any, id: string): any {
var n = tree.find(function (obj) { return obj.id === id; });
if (!n) {
tree.forEach(e => {
if (!n && e.children.length > 0) {
n = this.toggleSelectedTerm(e.children, id);
}
});
}
if (n && !n.edited) {
n.state.opened = !n.state.opened;
/* Add flag for avoid overwrite recursivity */
n.edited = true;
}
return n;
}
[note]Note
Just be care that the event is bind only once.
If you use this function :
var selectedNode = this.toggleSelectedTerm([buidTree return], [ID of selected term]);
don't forget to reset the flag added by the previous function
delete n.edited;
Next Step
Display the content of list or documents library in accordance with the selected term.