Introduction
Hi friends, this is part 6 where I will explain the usage of the PnP Animated Dialog control. We will see how we can leverage this control on our SPFx projects and make use of the feature provided by this control. Thanks to the community.
About the control
Most of us knows Dialog control helps us to display the contents that need confirmation or show information without have to redirect to a new page. Animated Dialog control is nothing but the same dialog control inherited from the default based dialog but we can add animation on top of the base dialog.
Focus on the Code
You can refer Part 1 post on the creation of the SPFx project and installing all the dependencies. In addition to the dependencies mentioned in that post you have to install @pnp/sp – v3.5.1. You should also do some changes to the project files to make the pnpjs version 3 to work on SPFx 1.14.0. Please follow this link to do the changes.
Created a web part named dialogsDemo. Below is the DialogsDemo.tsx file.
import * as React from 'react';
import styles from './DialogsDemo.module.scss';
import { IDialogsDemoProps } from './IDialogsDemoProps';
import { escape } from '@microsoft/sp-lodash-subset';
import { PrimaryButton, Stack } from 'office-ui-fabric-react';
import AnimDialog from '../../../common/AnimDialog';
import { useState } from 'react';
const DialogsDemo: React.FC<IDialogsDemoProps> = (props) => {
const {
description,
isDarkTheme,
environmentMessage,
hasTeamsContext,
userDisplayName
} = props;
const [showAnimDialog, setShowAnimDialog] = useState<boolean>(false);
const [animDialogScope, setAnimDialogScope] = useState<number>(0);
const [disableButtons, setDisableButtons] = useState<boolean>(false);
const _setDialogStatus = () => {
setShowAnimDialog(!showAnimDialog);
setDisableButtons(false);
};
const _showNormalAnimatedDialog = () => {
setShowAnimDialog(true);
setAnimDialogScope(0);
setDisableButtons(true);
};
const _showCustomAnimatedDialog = () => {
setShowAnimDialog(true);
setAnimDialogScope(1);
setDisableButtons(true);
};
const _showCustomAnimatedDialogWithIcon = () => {
setShowAnimDialog(true);
setAnimDialogScope(2);
setDisableButtons(true);
};
return (
<section className={`${styles.dialogsDemo} ${hasTeamsContext ? styles.teams : ''}`}>
<AnimDialog showDialog={showAnimDialog} setDialogStatus={_setDialogStatus} scope={animDialogScope} />
<Stack tokens={{ childrenGap: 10 }} horizontal>
<Stack.Item>
<PrimaryButton text="Show Animated Dialog" onClick={_showNormalAnimatedDialog}></PrimaryButton>
</Stack.Item>
<Stack.Item>
<PrimaryButton text="Show Custom Animated Dialog" onClick={_showCustomAnimatedDialog}></PrimaryButton>
</Stack.Item>
<Stack.Item>
<PrimaryButton text="Show Animated Dialog with Icon" onClick={_showCustomAnimatedDialogWithIcon}></PrimaryButton>
</Stack.Item>
</Stack>
</section>
);
};
export default DialogsDemo;
Below are the updates done to the file.
- Changed the class component to the react functional component
- Created some state variables to store the show or hide dialog values.
- Created 3 different methods to show some different dialogs
- Created 3 different methods to the show the dialogs
- Show Animated Dialog
- Show Custom Animated Dialog
- Show Animated Dialog with Icon
- Created a common component named AnimDialog and below are the properties that are passed to the common component
- showDialog – To show the dialog or not
- setDialogStatus – To set the state of the dialog to the normal state when clicking the close button or cancelling the dialog.
- scope – Numeric values to show different dialogs based on the button click.
Below is the code for the common component named AnimDialog.tsx
import * as React from 'react';
import styles from './AnimDialog.module.scss';
import { AnimatedDialog } from "@pnp/spfx-controls-react/lib/AnimatedDialog";
import { useState } from 'react';
import { DialogFooter, DialogType, IDialogContentProps } from 'office-ui-fabric-react/lib/Dialog';
import { DefaultButton, PrimaryButton } from 'office-ui-fabric-react/lib/Button';
import { IModalProps } from 'office-ui-fabric-react/lib/Modal';
export interface IAnimDialogProps {
showDialog: boolean;
setDialogStatus: () => void;
scope: number;
}
const AnimDialog: React.FC<IAnimDialogProps> = (props) => {
const [showDialog, setShowDialog] = useState<boolean>(false);
const [showSuccessDialog, setShowSuccessDialog] = useState<boolean>(false);
const [showErrorDialog, setShowErrorDialog] = useState<boolean>(false);
const animatedDialogContentProps: IDialogContentProps = {
type: DialogType.normal,
title: 'Animated Dialog',
subText: 'Do you like the animated dialog?',
};
const successDialogContentProps: IDialogContentProps = {
type: DialogType.normal,
title: 'Good answer!'
};
const errorDialogContentProps: IDialogContentProps = {
type: DialogType.normal,
title: 'Wrong answer!'
};
const animatedModalProps: IModalProps = {
isDarkOverlay: true,
isBlocking: true
};
const _hideDialog = () => {
setShowDialog(false);
props.setDialogStatus();
};
// The operation that does something - e.g. update data
const timeout = (ms: number): Promise<void> => {
return new Promise((resolve, reject) => setTimeout(resolve, ms));
};
const _onYesButtonClick = () => {
_hideDialog();
setShowSuccessDialog(true);
};
const _onNoButtonClick = () => {
_hideDialog();
setShowErrorDialog(true);
};
React.useEffect(() => {
setShowDialog(props.showDialog);
}, [props.showDialog]);
return (
<div className={styles.dialogContainer}>
{props.scope == 0 &&
<AnimatedDialog
hidden={!showDialog}
onDismiss={() => { _hideDialog(); }}
dialogContentProps={animatedDialogContentProps}
modalProps={animatedModalProps}
>
<DialogFooter>
<PrimaryButton onClick={() => { _hideDialog(); }} text="Yes" />
<DefaultButton onClick={() => { _hideDialog(); }} text="No" />
</DialogFooter>
</AnimatedDialog>
}
{props.scope == 1 &&
<AnimatedDialog
hidden={!showDialog}
onDismiss={() => { _hideDialog(); }}
dialogContentProps={animatedDialogContentProps}
modalProps={animatedModalProps}
dialogAnimationInType='fadeInDown'
dialogAnimationOutType='fadeOutDown'
>
<DialogFooter>
<PrimaryButton onClick={() => { _hideDialog(); }} text="Yes" />
<DefaultButton onClick={() => { _hideDialog(); }} text="No" />
</DialogFooter>
</AnimatedDialog>
}
{props.scope == 2 &&
<>
<AnimatedDialog
hidden={!showDialog}
onDismiss={() => { _hideDialog(); }}
dialogContentProps={animatedDialogContentProps}
modalProps={animatedModalProps}
iconName='UnknownSolid'
showAnimatedDialogFooter={true}
okButtonText="Yes"
cancelButtonText="No"
onOkClick={() => timeout(1500)}
onSuccess={() => _onYesButtonClick()}
onError={() => _onNoButtonClick()}
>
</AnimatedDialog>
<AnimatedDialog
hidden={!showSuccessDialog}
onDismiss={() => { setShowSuccessDialog(false); }}
dialogContentProps={successDialogContentProps}
modalProps={animatedModalProps}
iconName='CompletedSolid'
className={styles.dialogContainer}
>
<div className={styles.dialogContent}><span>Thank you.</span></div>
<div className={styles.resultDialogFooter}>
<PrimaryButton onClick={() => { setShowSuccessDialog(false); }} text="OK" >
</PrimaryButton>
</div>
</AnimatedDialog>
<AnimatedDialog
hidden={!showErrorDialog}
onDismiss={() => { setShowErrorDialog(false); }}
dialogContentProps={errorDialogContentProps}
modalProps={animatedModalProps}
iconName='StatusErrorFull'
className={styles.dialogContainer}
>
<div className={styles.dialogContent}><span>Try again!</span></div>
<div className={styles.resultDialogFooter}>
<PrimaryButton onClick={() => { setShowErrorDialog(false); }} text="OK" >
</PrimaryButton>
</div>
</AnimatedDialog>
</>
}
</div>
);
};
export default AnimDialog
- Import the AnimatedDialog component from the pnp controls
- Created some state variables and couple of DialogContentProps for different dialogs.
- Based on the scope, created different dialog control with different set of properties.
Reference URL
Animated Dialog – @pnp/spfx-controls-react
Sample Implementation

Conclussion
I hope you had learned something about one of the pnp control. There are lot to come in future.
Please free to post your comments and let me know if you want me to post article on any particular feature or plugins that relates to SharePoint. Thanks for your support.
sudharsank/pnpcontrols-demo: Demo project on different PnP React Controls. (github.com)
Happy Coding…