A few days before, I built a SharePoint Framework (SPFx) List view command set extension for the SharePoint document library named expense reports, so here I need to create a review files command, so once it is clicked, the file needs to be reviewed, which means it will update the Review and Reviewer fields.
Now, this list view command set extension is designed to work exclusively with the expense report SharePoint library, which contains the specific columns. However, deploying this extension will make it visible in all lists and libraries, which could be an issue. So here I was required to restrict to a particular library.
In this article, I will explain how to restrict the SPFx list view command set extension to a specific list/library.
SPFx Extensions ListView Command Set to Specific List/ Library
In the SharePoint Framework, the list view command set extension is one of the four different extensions. This extension is used to customize the command bar or context menu in SharePoint lists and libraries with custom commands.
Now, the highlighted part in the image below indicates the command bar in the SharePoint list and library.

And this highlighted part indicates the context menu.

In those two places, we can add our custom commands and perform actions with them. Now, let’s start by creating the list view command set extension.
- Create a new directory in your specified location by running the command below in the command prompt.
md SPFxListViewCmdSet
- Now, enter this directory by running the command below.
cd SPFxListViewCmdSet
- Then, to create a project structure for the list view command set extension, run the command below.
yo @micorosft/sharepoint
- Then it will ask you the following questions, provide the answers as I gave.
- What is your solution name? SPFxListViewCmdSet
- Which type of client-side component to create? Extension
- Which type of client-side extension to create? ListView Command Set
- Add new Command Set to the solution sp-fx-list-view-cmd-set.
- What is your Command Set name? ReviewFilesExt

- Once it creates the extension, run the command below to open Visual Studio Code.
code .
- So, here you can see the folder structure of the list view command set extension, which is almost similar to a webpart. The files marked below play a significant role, so let’s discuss each one at a time.

- The ClientSideInstance.xml file and the elements.xml files are useful while deploying, registering the extension to the SharePoint list/library, and testing the solution.
This is the code present in the elements.xml file.
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<CustomAction
Title="ReviewFilesExt"
RegistrationId="100"
RegistrationType="List"
Location="ClientSideExtension.ListViewCommandSet.CommandBar"
ClientSideComponentId="2e2f63b5-3bd6-4a88-8d08-b8dcbe35050a"
ClientSideComponentProperties="{"sampleTextOne":"One item is selected in the list.", "sampleTextTwo":"This command is always visible."}">
</CustomAction>
</Elements>
Which contains a custom action that has the following values:
- Title = Extension title.
- RegistrationId = Indicates the list IDs, 100 for the list and 101 for the library.
- RegistrationType = Either list or library.
- Location = Where to register the extension, either in the command bar, the context menu, or both.
- ClientSideComponentId = A unique ID is generated for the list view command set extension, which is also present in the manifest.json file.
- ClientSideComponentProperties = For specific configurations, we can use these properties.
While testing locally, this extension will work for both lists and libraries. Once it is deployed, it will only work for lists because we haven’t provided another custom action for libraries. To make this extension work for the library, add a new custom action with RegistrationId 101 as shown below.
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<CustomAction
Title="ReviewFilesExt"
RegistrationId="100"
RegistrationType="List"
Location="ClientSideExtension.ListViewCommandSet.CommandBar"
ClientSideComponentId="2e2f63b5-3bd6-4a88-8d08-b8dcbe35050a"
ClientSideComponentProperties="{"sampleTextOne":"One item is selected in the list.", "sampleTextTwo":"This command is always visible."}">
</CustomAction>
<CustomAction
Title="ReviewFilesExt"
RegistrationId="101"
RegistrationType="List"
Location="ClientSideExtension.ListViewCommandSet.CommandBar"
ClientSideComponentId="2e2f63b5-3bd6-4a88-8d08-b8dcbe35050a"
ClientSideComponentProperties="{"sampleTextOne":"One item is selected in the list.", "sampleTextTwo":"This command is always visible."}">
</CustomAction>
</Elements>
We can use the ClientSideInstance.xml file to deploy our extension across all sites in our tenant automatically.
- Then, coming to the .ts file present within the src/extension folder. This is the file where we need to implement our logic. It mainly contains the following three functions:
- onInit()
- onExecute()
- _onListViewStateChanged()
Let’s understand what each function is doing:
- In the onInit() method, using the tryGetCommand() method, one command [COMMAND_1] is created and that is stored in the compareOneCommand variable.
- Then, we set its visible property to false by default, so this command won’t be visible in the list/library when the extension is added, the this.context.listView returns the current view, and the listViewStateChangedEvent triggers when actions are taken in the list view. At that point, we call the _onListViewStateChanged() function.
public onInit(): Promise<void> {
Log.info(LOG_SOURCE, 'Initialized ReviewFilesExtCommandSet');
// initial state of the command's visibility
const compareOneCommand: Command = this.tryGetCommand('COMMAND_1');
compareOneCommand.visible = false;
this.context.listView.listViewStateChangedEvent.add(this, this._onListViewStateChanged);
return Promise.resolve();
}
- The onListViewStateChanged() method controls the visibility of the command in list/library view based on specific conditions. For instance, the if condition below sets the command’s visibility to true whenever a single row in the list view is selected.
private _onListViewStateChanged = (args: ListViewStateChangedEventArgs): void => {
Log.info(LOG_SOURCE, 'List view state changed');
const compareOneCommand: Command = this.tryGetCommand('COMMAND_1');
if (compareOneCommand) {
// This command should be hidden unless exactly one row is selected.
compareOneCommand.visible = this.context.listView.selectedRows?.length === 1;
}
// TODO: Add your logic here
// You should call this.raiseOnChage() to update the command bar
this.raiseOnChange();
}
- In the onExecute() method, we can write the code that specifies the action to perform when the command is clicked. So, in this default example, when we click the commands, it displays a dialog box with a sample message.
public onExecute(event: IListViewCommandSetExecuteEventParameters): void {
switch (event.itemId) {
case 'COMMAND_1':
Dialog.alert(`${this.context.pageContext.list?.title}`).catch(() => {
/* handle error */
});
break;
case 'COMMAND_2':
Dialog.alert(`${this.context.pageContext.list?.title}`).catch(() => {
/* handle error */
});
break;
default:
throw new Error('Unknown command');
}
}
- Now, to restrict the list view command set extension to a specified SharePoint library/list, update the two functions as follows.
public onInit(): Promise<void> {
Log.info(LOG_SOURCE, 'Initialized ReviewFilesExtCommandSet');
const compareOneCommand: Command = this.tryGetCommand('COMMAND_1');
if (compareOneCommand &&this.context.pageContext.list && this.context.pageContext.list.title === "ExpenseReports" ) {
compareOneCommand.visible = true;
this.raiseOnChange();
}
else{
compareOneCommand.visible = false;
}
this.context.listView.listViewStateChangedEvent.add(this, this._onListViewStateChanged);
return Promise.resolve();
}
private _onListViewStateChanged = (args: ListViewStateChangedEventArgs): void => {
Log.info(LOG_SOURCE, 'List view state changed');
const compareOneCommand: Command = this.tryGetCommand('COMMAND_1');
if (compareOneCommand) {
compareOneCommand.visible = this.context.listView.selectedRows?.length === 1 && this.context.pageContext.list?.title === "ExpenseReports" ;
}
// TODO: Add your logic here
// You should call this.raiseOnChage() to update the command bar
this.raiseOnChange();
}

In the onInit() and _onListViewStateChanged() methods, I made the command one visible if the current list or library name matches the “ExpenseReports” name.
- Before going to test, let’s understand one more important file, the manifest.json file.
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx/command-set-extension-manifest.schema.json",
"id": "2e2f63b5-3bd6-4a88-8d08-b8dcbe35050a",
"alias": "ReviewFilesExtCommandSet",
"componentType": "Extension",
"extensionType": "ListViewCommandSet",
// The "*" signifies that the version should be taken from the package.json
"version": "*",
"manifestVersion": 2,
// If true, the component can only be installed on sites where Custom Script is allowed.
// Components that allow authors to embed arbitrary script code should set this to true.
// https://support.office.com/en-us/article/Turn-scripting-capabilities-on-or-off-1f2c515f-5d7e-448a-9fd7-835da935584f
"requiresCustomScript": false,
"items": {
"COMMAND_1": {
"title": { "default": "Command One" },
"iconImageUrl": "icons/request.png",
"type": "command"
},
"COMMAND_2": {
"title": { "default": "Command Two" },
"iconImageUrl": "icons/cancel.png",
"type": "command"
}
}
}
This file contains the information about this extension, like ID, alias, componentType, and extensionType. Then, in the “items” array, you can see that two commands are created for this extension, and each extension has the title, iconImageUrl, and type. So, you can change these properties if you want.
I’ve updated Command One’s title and its icon image URL by adding a review image to the icons folder, as shown in the image below.
"items": {
"COMMAND_1": {
"title": { "default": "Review Files" },
"iconImageUrl": "./icons/review.png",
"type": "command"
},
"COMMAND_2": {
"title": { "default": "Command Two" },
"iconImageUrl": "./icons/review.png",
"type": "command"
}
}

- Now, it’s time to test and deploy the list view command set extension. You can test it locally by running the command below.
Before proceeding, update the “pageUrl” in the config/serve.json file with your SharePoint list or library URL, as shown below. Then, you can see the “location” parameter on the right, which indicates where our extension is going to be presented, so currently we mentioned CommandBar.
gulp serve

- Once you run gulp serve, it will launch the URL specified in the serve.json file. To test the list view command set extension locally, click the Load debug scripts button.

Then, refresh one or two times, and you can see the commands for the SharePoint document library, as shown below.

- Let’s deploy the solution, so run the commands below to package this extension.
gulp bundle --ship
gulp package-solution --ship
Then you will see the .sppkg file in the /SharePoint/solution/sp-fx-list-view-cmd-set.sppkg. Upload this file into either the SharePoint site collection app catalog or the tenant app catalog.
After deploying the package file, the command one [Review Files] in the list view command set extension is only visible in the “ExpenseDocuments” library, since we didn’t restrict any visibility condition for command two, it is available in all lists and libraries.

Note: If you don’t want the second command, remove the code below from the manifest.json file.
"COMMAND_2": {
"title": { "default": "Command Two" },
"iconImageUrl": "./icons/review.png",
"type": "command"
}
Or
To restrict the command two to the specified library or list, update the if condition in the .ts file’s onInit() method as shown below.
public onInit(): Promise<void> {
Log.info(LOG_SOURCE, 'Initialized ReviewFilesExtCommandSet');
const compareOneCommand: Command = this.tryGetCommand('COMMAND_1');
const comparetwoCommand: Command = this.tryGetCommand('COMMAND_2');
if (compareOneCommand && comparetwoCommand&&this.context.pageContext.list && this.context.pageContext.list.title === "ExpenseReports" ) {
compareOneCommand.visible = true;
this.raiseOnChange();
}
else{
compareOneCommand.visible = false;
}
this.context.listView.listViewStateChangedEvent.add(this, this._onListViewStateChanged);
return Promise.resolve();
}
Here, I created command two using the tryGetCommand() method and stored it in the compareTwoCommand variable. Then, in the if condition, I included both command one and command two, making the visibility condition applicable to both commands. So both commands are only visible in one library.

This way, we restrict the SPFx list view command set extension to a specified SharePoint list or library.
I hope you found this article helpful! In this article, I have explained what a SharePoint Framework (SPFx) list view command set extension is, and how to restrict it to a particular list or library. Follow this article if you are also looking to restrict the SPFx list view command set extension to a specific list or library.
Also, you may like:
- SharePoint Framework User Profile Web Part [Using MS Graph API]
- Configure SharePoint Framework Web Part Icon
- How to Add Multiple WebParts To Single SPFx Solution?
- Create a SharePoint List using SharePoint Framework [Including Adding Columns]
- Create Folders and Subfolders in SharePoint document library using SPFx

Hey! I’m Bijay Kumar, founder of SPGuides.com and a Microsoft Business Applications MVP (Power Automate, Power Apps). I launched this site in 2020 because I truly enjoy working with SharePoint, Power Platform, and SharePoint Framework (SPFx), and wanted to share that passion through step-by-step tutorials, guides, and training videos. My mission is to help you learn these technologies so you can utilize SharePoint, enhance productivity, and potentially build business solutions along the way.