SPFx 1.14 List View Command Set Updates
Tags: spfx
Published: 2022-03-28 13:52:51

The [SPFx v1.14](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/release-1.14#list-view-command-set-updates) 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](https://github.com/SharePoint/sp-dev-docs/issues/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
```typescript
public onInit(): Promise<void> {
    this.context.listView.listViewStateChangedEvent.add(this, this.onListViewUpdatedv2);

}
public onListViewUpdatedv2(args: ListViewStateChangedEventArgs): void{
}
```

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](https://github.com/SharePoint/sp-dev-docs/issues/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
```typescript
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();
  }
}
```

See working example on [GitHub](https://github.com/kkazala/spfx-Panel):

![Example of the extension in action](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vyj4ddpfctsj4i647gv0.gif)