1

I have extension which uses the term store as navigation and on the other hand, I have dropdown list where it has the normal text (SiteA, SiteB, SiteC) with different SP site links on it (href). So, when I click it, I navigate to another site but the navigation from term store is not loaded on this navigated site.

Means it loads the previous site navigation from term store, however after some time (15 mins) when I hit refresh then it loads the navigation.

Not sure how I can make the other sites load navigation as soon as I navigate from one site to another.

  @override
public onInit(): Promise<void> {
  Log.info(LOG_SOURCE, `Initialized ${strings.Title}`);
  this.context.application.navigatedEvent.add(this, () => {
    Log(LOG_SOURCE, 'Navigated event');
    this.termStoreloadingMethod();
  });
  super.onInit().then(_ => {
    console.log("super oninit called");
    sp.setup({
      spfxContext: this.context,
      defaultCachingStore: "local",
      defaultCachingTimeoutSeconds: 30,
      globalCacheDisable: false
    });
  }).then((_) => {
    console.log("Sp Initilize");
    this.context.placeholderProvider.changedEvent.add(this, this._renderPlaceHolders);
  });

.tsx

    private store = new PnPClientStorage();
    constructor(props: IGlobalNavProps) {
        super(props);
        this.state = {
            
            loading: false,
            terms: []
        };
    }
    
public componentDidMount() {
        this.setState({}, async () => {
            // this portion is responsible for getting terms from term store
            const cachedTermInfo = await this.store.local.getOrPut(myKey, () => {
                return sp.termStore.groups.getById(this.props.termGroupId).sets.getById(this.props.termSetId).getAllChildrenAsOrderedTree({ retrieveProperties: true });
            }, dateAdd(new Date(), "minute", 10));
            if (cachedTermInfo.length > 0) {
                console.log(cachedTermInfo);
                this.setState({ terms: cachedTermInfo });
            }
        });
    }

    private menuItems(menuItem: any, itemType: ContextualMenuItemType) {
        return ({
            
            key: menuItem.id,
            name: menuItem.defaultLabel,
            itemType: itemType,
            href: menuItem.children.length == 0 ?
                ((menuItem.localProperties != undefined && menuItem.localProperties[0].properties !== undefined && menuItem.localProperties[0].properties.length > 0) ?
                    menuItem.localProperties[0].properties.filter(x => x.key == "_Sys_Nav_SimpleLinkUrl")[0].value !== undefined ? menuItem.localProperties[0].properties.filter(x => x.key == "_Sys_Nav_SimpleLinkUrl")[0].value : null
                    : null)
                : null,
            subMenuProps: menuItem.children.length > 0 ?
                { items: menuItem.children.map((i) => { return (this.menuItems(i, ContextualMenuItemType.Normal)); }) }
                : null,
            isSubMenu: itemType != ContextualMenuItemType.Header,
            buttonStyles: buttonStyle
        });
    }
    
    public render(): React.ReactElement<IGlobalNavProps> {
        
        var commandBarItems: any[] = [];
        if (this.state.terms.length > 0) {
            commandBarItems = this.state.terms.map((i) => {
                return (this.menuItems(i, ContextualMenuItemType.Header));
            });
        }

This is what my onInit looks like but I get error when I add the code.

"Value of type 'typeof Log' is not callable. Did you mean to include 'new'?ts(2348) " and Property 'termStoreloadingMethod' does not exist on type 'NavApplicationCustomizer'.ts

1 Answer 1

0

You'll need to subscribe to navigation events and reload as needed. Extensions aren't reloaded as users navigate, instead they are notified of the navigation and the code needs to respond appropriately.

Try adapting this version of your onInit:

@override
public onInit(): Promise<void> {
  Log.info(LOG_SOURCE, `Initialized ${strings.Title}`);
  
  return super.onInit().then(_ => {
    Log.verbose("super oninit called");

    sp.setup({
      spfxContext: this.context,
      defaultCachingStore: "local",
      defaultCachingTimeoutSeconds: 30,
      globalCacheDisable: false
    });

    this.context.placeholderProvider.changedEvent.add(this, this._renderPlaceHolders);

    this.context.application.navigatedEvent.add(this, () => {
      Log.info(LOG_SOURCE, 'Navigated event');
      this._termStoreloadingMethod();
    });

    this._termStoreLoadingMethod();
  });
}

Keep in mind:

  • The _termStoreloadingMethod referenced above is not a real method. This is a placeholder for whatever method in your code that uses PnPJS to load the term store values.
  • The Log requires an import at the top: import { Log } from '@microsoft/sp-core-library';
  • To see the log entries, press Ctrl+F12 on your SharePoint page
3
  • Well tried with the above code but I see error message, I have updated in my original question.
    – striker92
    Feb 21, 2023 at 15:25
  • @striker92 I've updated my answer with a little more detail and also addressed the errors received with Log - hope it helps! Feb 22, 2023 at 18:52
  • Thanks for the suggestion, I am bit lost with _termStoreloadingMethod so far I have called the method as like this private _termStoreloadingMethod = (): void => { console.log('%c Navigated', 'background: green; color: white; display: block; size: 20px'); console.log('Context:'); console.log(this.context); } . Please let me know if needs correction or any reference link so that I can check. Also added tsx in the main question where I am getting terms
    – striker92
    Feb 23, 2023 at 8:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.