SPFx 1.14 List View Command Set Updates

kkazala

Kinga

Posted on March 28, 2022

SPFx 1.14 List View Command Set Updates

The SPFx v1.14 has few, very exciting capabilities for List View Command Sets.

raiseOnChange

raiseOnChange() does NOT do what you think it does. The documentation promises initializing a reflow of the ListView but we are supposed to use it to update the command set, not the list view.
See issue #7811

If raiseOnChange() seems to work with some delay, it's because SPO lists refresh the content on regular basis.

listViewStateChangedEvent

Newly provisioned projects still use the deprecated onListViewUpdated event, but we can update the code to use the new listViewStateChanged.

CommandSet.ts

public onInit(): Promise<void> {
    this.context.listView.listViewStateChangedEvent.add(this, this.onListViewUpdatedv2);

}
public onListViewUpdatedv2(args: ListViewStateChangedEventArgs): void{
}
Enter fullscreen mode Exit fullscreen mode

SPFx v1.15 will use updated template with listViewStateChanged

Show the button for a specific list only

Let's assume that I only want to show the button for a specific list (e.g. Travel Requests). In order to hide it in other lists, I need to get the list title/url from the current context.

The listViewStateChangedEvent is not executed on first render, so I cannot use it to hide the button. I have to hide it during onInit.

There are two properties returning list context:

  • this.context.pageContext.list.serverRelativeUrl, but it does not refresh the list context correctly
  • this.context.listView.list.serverRelativeUrl but it returns undefined when debugging

See issue #7795

I'm therefore hiding the button during onInit, and show it (or not) during listViewStateChangedEvent. listViewStateChangedEvent is the moment I need to call raiseOnChange to ensure the button will be displayed.

CommandSet.ts

public onInit(): Promise<void> {

  const _setCommandsHidden = () => {
    const compareOneCommand: Command = this.tryGetCommand('COMMAND_1');
    if (compareOneCommand) {
      compareOneCommand.visible = false;
    }
    const compareTwoCommand: Command = this.tryGetCommand('COMMAND_2');
    if (compareTwoCommand) {
      compareTwoCommand.visible = false;
    }
  }

  _setCommandsHidden();
  return Promise.resolve();
}

public onListViewUpdatedv2(args: ListViewStateChangedEventArgs): void{

  Logger.write("onListViewUpdatedv2");

  const isCorrectList = (this.context.listView.list.title == "Travel requests") ? true : false;
  const itemSelected = this.context.listView.selectedRows && this.context.listView.selectedRows.length == 1;

  let raiseOnChange: boolean = false;

  const compareOneCommand: Command = this.tryGetCommand('COMMAND_1');
  if (compareOneCommand && (compareOneCommand.visible != isCorrectList )) {
    compareOneCommand.visible = isCorrectList;
    raiseOnChange = true;
  }

  const compareTwoCommand: Command = this.tryGetCommand('COMMAND_2');
  if (compareTwoCommand && (compareTwoCommand.visible!= (isCorrectList && itemSelected))) {
    compareTwoCommand.visible = isCorrectList && itemSelected;
    raiseOnChange = true;
  }

  if (raiseOnChange) {
    this.raiseOnChange();
  }
}
Enter fullscreen mode Exit fullscreen mode

See working example on GitHub:

Example of the extension in action

馃挅 馃挭 馃檯 馃毄
kkazala
Kinga

Posted on March 28, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related