Working with Taxonomy is always a fun, because accessing terms from it requires us to write different way of code. SharePoint doesn’t provide the direct way of accessing the terms through REST API. We still require client.svc support for managing the taxonomy.

PnPjs library gives us the different methods and properties for managing the taxonomy, termgroup, termsets, termstores, terms and taxonomysessions.

We have to first install the below npm command to import taxonomy pnpjs modules in to our project,

npm install @pnp/logging @pnp/common @pnp/odata @pnp/sp @pnp/sp-taxonomy @pnp/sp-clientsvc –save

@pnp/sp-taxonomy and @pnp/sp-clientsvc modules are required in the project to call taxonomy related methods and properties.

//Returns the termstore based on the name.
taxonomy.termStores.getByName("Taxonomy_kmABCdLRj1sbZy/jQhkZ+A==")
//Returns the termsets from the termgroup
<termstore>.getTermGroupById("abcde73e-99f3-4112-89ed-431e98111a1z").termSets
//Returns the terms from the termset
<termset>.terms 

The below code returns the collection of the all terms across all the termsets from the retrieved termstore.

import { taxonomy, ITerm, ITermSet, ITermStore } from '@pnp/sp-taxonomy';
//
//
public async getTermsetWithChildren(): Promise<any[]> {
    let tms: any[] = [];
    return new Promise<any[]>((resolve, reject) => {
      const tbatch = taxonomy.createBatch();
      return taxonomy.termStores.getByName("Taxonomy_kmRTKbLRj1sbZy/jQhkX+A==").get().then((resp1: ITermStore) => {        
        return resp1.getTermGroupById("cfaeb73e-99f3-4112-89ed-431e98858e7f").termSets.get().then((resp2: ITermSet[]) => {
          resp2.forEach((ele: ITermSet) => {
            ele.terms.select('Name', 'Id').inBatch(tbatch).get().then((r3: ITerm[]) => {
              r3.forEach((t1: ITerm) => {
                let ip1 = {
                  parent: ele['Name'],
                  name: t1['Name'],
                  id: t1['Id'].replace("/Guid(", "").replace(")/", "")
                };
                tms.push(ip1);
              });
            });
          });
          tbatch.execute().then(_r => {
            resolve(tms);
          });
        });
      });
    });
  }

we’ll see how to use the above code to fetch all terms across all termsets with a single taxonomy batch in SharePoint Framework webpart using pnpjs library.

Create a SharePoint Framework webpart project using

yo @microsoft/sharepoint

Then install pnpjs module to the spfx project. I have create a project name called “TaxonomyPopulator” and use the below code to show all terms in table in react based spfx webpart.

//TaxonomyPopulator.tsx
import * as React from 'react';
import styles from './TaxonomyPopulator.module.scss';
import { ITaxonomyPopulatorProps } from './ITaxonomyPopulatorProps';
import { taxonomy, ITerm, ITermSet, ITermStore } from '@pnp/sp-taxonomy';

export interface IPTerm {
  parent?: string;
  id: string;
  name: string;
}

export interface ITaxonomyPopulatorState {
  terms: IPTerm[];
}

export default class TaxonomyPopulator extends React.Component<ITaxonomyPopulatorProps, ITaxonomyPopulatorState> {
  constructor(props) {
    super(props);
    this.state = {
      terms: []
    };
  }

  public async getTermsetWithChildren(): Promise<IPTerm[]> {
    let tms: IPTerm[] = [];
    return new Promise<any[]>((resolve, reject) => {
      const tbatch = taxonomy.createBatch();
      return taxonomy.termStores.getByName("Taxonomy_kmABCdLRj1sbZy/jQhkZ+A==").get().then((resp1: ITermStore) => {        
        return resp1.getTermGroupById("abcde73e-99f3-4112-89ed-431e98111a1z").termSets.get().then((resp2: ITermSet[]) => {
          resp2.forEach((ele: ITermSet) => {
            ele.terms.select('Name', 'Id').inBatch(tbatch).get().then((resp3: ITerm[]) => {
              resp3.forEach((t: ITerm) => {
                let ip1 = {
                  parent: ele['Name'],
                  name: t['Name'],
                  id: t['Id'].replace("/Guid(", "").replace(")/", "")
                };
                tms.push(ip1);
              });
            });
          });
          tbatch.execute().then(_r => {
            resolve(tms);
          });
        });
      });
    });
  }

  public componentDidMount() {
    this.getTermsetWithChildren().then((resp: IPTerm[]) => {
      console.log(resp);
      this.setState({
        terms: resp
      });
    });
  }

  public render(): React.ReactElement<ITaxonomyPopulatorProps> {
    let termrow = this.state.terms.map((t: IPTerm) => {
      return <tr> <td>{t.name}</td><td>{t.id}</td><td>{t.parent}</td></tr>;
    });
    return (      
<div className={styles.taxonomyPopulator}>        
<div className={styles.container}>          
<div className={styles.row}>            
<div className={styles.column}>
              <span className={styles.title}>Terms from TermStore</span>
            </div>
          </div>          
<table>        
<thead><tr><th>Name</th><th>Id</th><th>Parent</th></tr></thead>            
<tbody>{termrow}</tbody>
          </table>
        </div>
      </div>);
  }  
}

The method getTermsetWithChildren() creates the the batch request and pushes all the terms request in to the tbatch = taxonomy.createBatch() by including in each request like below,

terms.select('Name', 'Id').inBatch(tbatch).get().then(())

After adding the above code to the SharePoint Framework project and we will get the below output,