DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» is a community of 968,547 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Kinga
Kinga

Posted on • Updated on

Panel for ListView Command Set (SharePoint Online)

Although SharePoint Online displays list forms in a panel, all the examples and samples for ListView Command Sets are using dialog controls.

Typically, it's a no-brainer to open/close panel if it's controlled by a parent component. In the case of ListView Command Set, this requires slightly more effort.

Panel

The StatefulPanel component is using isOpen state to control Panel state. Once it's dismissed, the isOpen is set to false, and a props.onDismiss() method is executed. This is important if you need to refresh the page, after the StatefulPanel is closed.

To make sure the StatefulPanel may be used the same way a regular Panel is, the type of the props is wrapped in React.PropsWithChildren.

StatefulPanel.tsx
export interface IStatefulPanelProps {
    title: string;
    shouldOpen: boolean;
    panelTop: number;
    onDismiss?: any;
}

export default function StatefulPanel(props: React.PropsWithChildren<IStatefulPanelProps>){

    const [isOpen, setisOpen] = useBoolean(false);

    React.useEffect(() => {
        if (props.shouldOpen && !isOpen ) { 
            setisOpen.setTrue();
            props.shouldOpen = false;
        }
    }, [props.shouldOpen]);

    const _onPanelClosed = () => {
        setisOpen.setFalse();
        if (props.onDismiss) { 
            props.onDismiss();
        }
    };

    return <Panel
        headerText={props.title}
        isOpen={isOpen}
        type={PanelType.medium}
        isLightDismiss={false}
        onDismiss={_onPanelClosed}>
                {props.children}
        </Panel>;
}
Enter fullscreen mode Exit fullscreen mode

MyComponent wraps all the Forms/Lists/Controls in the StatefulPanel.

MyComponent.tsx
export interface IMyComponentProps { 
    selectedRows: readonly RowAccessor[];
    context: ListViewCommandSetContext;
    panelConfig: IStatefulPanelProps;
}

export default function MyComponent(props: IMyComponentProps) {
    const [refreshPage, setRefreshPage] = useBoolean(false);

    const _onPanelClosed = () => {
        if (refreshPage) {
            //Reloads the entire page since there isn't currently a way to just reload the list view
            location.reload(); 
        }
    };

    return <StatefulPanel
        title={props.panelConfig.title}
        panelTop={props.panelConfig.panelTop}
        shouldOpen={props.panelConfig.shouldOpen}
        onDismiss={_onPanelClosed}
    >
        <Toggle
            label="Refresh the page when panel closes:"
            inlineLabel
            onChange={setRefreshPage.toggle}
            onText="Yes"
            offText="No"
            defaultChecked={refreshPage} />
    </StatefulPanel>;
}
Enter fullscreen mode Exit fullscreen mode

The CommandSet code requires minimal changes to replace Dialog with a Panel.

PanelCommandSet.ts
export default class PanelCommandSet extends BaseListViewCommandSet<IPanelCommandSetProperties> {
  private panelPlaceHolder: HTMLDivElement = null;
  private panelTop: number;

  private _showComponent = (props: IMyComponentProps): void => { 
    ReactDOM.render(React.createElement(MyComponent, props), this.panelPlaceHolder);
  }

  @override
  public onInit(): Promise<void> {
    this.panelTop = document.querySelector("#SuiteNavWrapper").clientHeight;
    this.panelPlaceHolder = document.body.appendChild(document.createElement("div"));
    return Promise.resolve();
  }

  @override
  public onExecute(event: IListViewCommandSetExecuteEventParameters): void {

    switch (event.itemId) {
      case 'COMMAND_1':
        this._showComponent({
          panelConfig: {
            panelTop:this.panelTop,
            shouldOpen:true,
            title: "Panel",
          },
          selectedRows: event.selectedRows,
          context: this.context,
        });
        break;
      default:
        throw new Error('Unknown command');
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

You can see the source code here: https://github.com/kkazala/spfx-Panel
Or, if you prefer to try it our right away, the packaged solution is here.

UPDATE 17.01.2022: I just created a suggestion to update @microsoft/generator-sharepoint, to create Panel instead of Dialog. Please vote it up if you agree =)

Top comments (0)

🌚 Friends don't let friends browse without dark mode.

Sorry, it's true.