|
1 | 1 | # Using Custom Dialogs with SharePoint Framework Extensions
|
2 | 2 |
|
3 |
| -Introduction |
| 3 | +Custom dialogs are available from `@microsoft/sp-dialog`package and can be used within the context of SharePoint Framework Extensions or client-side web parts. |
4 | 4 |
|
5 |
| -Dialog is also avaialble for web parts. |
| 5 | +This tutorial demonstrates creation of a custom dialog and using that in the context of ListView Command Set extension. |
6 | 6 |
|
7 | 7 | > Notice that the SharePoint Framework dialog is currently in preview status and we are looking to collect feedback before it's officially released. Please provide us feedback by using the [sp-dev-docs repository Issue list](https://github.com/SharePoint/sp-dev-docs/issues).
|
8 | 8 |
|
| 9 | +> Notice that debugging Custom ListView Sets in the SharePoint Online is currently only available from modern list experience in classic team sites hosted on dev tenant. |
| 10 | +
|
| 11 | +> End result of this tutorial is also available as source code at https://github.com/SharePoint/sp-dev-fx-extensions/tree/master/samples/react-command-dialog. |
| 12 | +
|
9 | 13 | ## Setup your Environment
|
10 | 14 |
|
11 | 15 | Before you can complete this guide you will need to ensure you have [setup your environment](https://dev.office.com/sharepoint/docs/spfx/set-up-your-development-environment) for development
|
@@ -44,17 +48,232 @@ The next set of prompts will ask for specific information about your extension:
|
44 | 48 | * Accept the default value of **DialogDemo** as your extension name and press **Enter**.
|
45 | 49 | * Accept the default value of **DialogDemo description** as your extension description and press **Enter**.
|
46 | 50 |
|
47 |
| - |
| 51 | + |
48 | 52 |
|
49 |
| -At this point, Yeoman will install the required dependencies and scaffold the solution files along with the **HelloWorld** extension. This might take a few minutes. |
| 53 | +At this point, Yeoman will install the required dependencies and scaffold the solution files along with the *HelloWorld* extension. This might take a few minutes. |
50 | 54 |
|
51 | 55 | When the scaffold is complete, you should see the following message indicating a successful scaffold:
|
52 | 56 |
|
53 |
| - |
| 57 | + |
54 | 58 |
|
55 | 59 | For information about troubleshooting any errors, see [Known issues](../basics/known-issues).
|
56 | 60 |
|
57 |
| -Once the solution scaffolding is completed, type the following into the console to start Visual Studio Code. |
| 61 | +Once the scaffolding completes, open your project folder in your code editor. This article uses Visual Studio Code in the steps and screenshots but you can use any editor you prefer. |
| 62 | + |
| 63 | +``` |
| 64 | +code . |
| 65 | +``` |
| 66 | + |
| 67 | + |
| 68 | + |
| 69 | +## Modify extension manifest based on requirements |
| 70 | + |
| 71 | +In the extension manifest, configure extension to have only one button. In the code editor, open the **./src/extensions/dialogDemo/DialogDemoCommandSet.manifest.json** file. Replace the commands section with the following JSON: |
| 72 | + |
| 73 | +```json |
| 74 | +{ |
| 75 | + //... |
| 76 | + "commands": { |
| 77 | + "COMMAND_1": { |
| 78 | + "title": "Open Custom Dialog", |
| 79 | + "iconImageUrl": "icons/request.png" |
| 80 | + } |
| 81 | + } |
| 82 | +} |
| 83 | + |
| 84 | +``` |
| 85 | + |
| 86 | +## Adding sp-dialog package to solution |
| 87 | +Return to the console and execute the following command to include the dialog API in our solution. |
| 88 | + |
| 89 | +``` |
| 90 | +npm install @microsoft/sp-dialog --save |
| 91 | +``` |
| 92 | + |
| 93 | +Since we are using the `--save` option, this dependency will be added to *package.json* file and would be automatically installed when `npm install` command is executed. |
| 94 | + |
| 95 | +Return to Visual Studio Code (or your preferred editor). |
| 96 | + |
| 97 | +## Creating your custom dialog |
| 98 | +Create a new file called **ColorPickerDialog.tsx** to **./src/extensions/dialogDemo/** folder. |
| 99 | + |
| 100 | +Add following import statements on the start of the newly created file. We are creating our custom dialog using Office UI Fabric React components, so the implementation will be in React. |
| 101 | + |
| 102 | +> Notice that currently DialogContent component is coming from `@microsoft/sp-dialog`, but will be included in Office UI Fabric React components soon, like mentioned in the code comments. |
| 103 | +
|
| 104 | +```ts |
| 105 | +import * as React from 'react'; |
| 106 | +import * as ReactDOM from 'react-dom'; |
| 107 | +import { BaseDialog, IDialogConfiguration } from '@microsoft/sp-dialog'; |
| 108 | +import { |
| 109 | + autobind, |
| 110 | + ColorPicker, |
| 111 | + PrimaryButton, |
| 112 | + Button, |
| 113 | + DialogFooter |
| 114 | + // DialogContent <- This should be imported here for third parties |
| 115 | +} from 'office-ui-fabric-react'; |
| 116 | +// Note: DialogContent is available in v2.32.0 of office-ui-fabric-react |
| 117 | +// As a workaround we're importing it from sp-dialog until the next version bump |
| 118 | +import { DialogContent } from '@microsoft/sp-dialog'; |
| 119 | +``` |
| 120 | + |
| 121 | +Add following interface definition just below the import statements. This wil be used to bypass needed information and functions between the ListView Command Set extension and custom dialog. |
| 122 | + |
| 123 | +```ts |
| 124 | +interface IColorPickerDialogContentProps { |
| 125 | + message: string; |
| 126 | + close: () => void; |
| 127 | + submit: (color: string) => void; |
| 128 | + defaultColor?: string; |
| 129 | +} |
| 130 | +``` |
| 131 | + |
| 132 | +Add following class just below the interface definition. This React class is responsible for rendering the UI experiences inside of the custom dialog. Notice that we use the Office UI Fabric React components for actual rendering and just bypass the needed properties. |
| 133 | + |
| 134 | +```ts |
| 135 | +class ColorPickerDialogContent extends React.Component<IColorPickerDialogContentProps, {}> { |
| 136 | + private _pickedColor: string; |
| 137 | + |
| 138 | + constructor(props) { |
| 139 | + super(props); |
| 140 | + // Default Color |
| 141 | + this._pickedColor = props.defaultColor || '#FFFFFF'; |
| 142 | + } |
| 143 | + |
| 144 | + public render(): JSX.Element { |
| 145 | + return <DialogContent |
| 146 | + title='Color Picker' |
| 147 | + subText={this.props.message} |
| 148 | + onDismiss={this.props.close} |
| 149 | + showCloseButton={true} |
| 150 | + > |
| 151 | + <ColorPicker color={this._pickedColor} onColorChanged={this._onColorChange} /> |
| 152 | + <DialogFooter> |
| 153 | + <Button text='Cancel' title='Cancel' onClick={this.props.close} /> |
| 154 | + <PrimaryButton text='OK' title='OK' onClick={() => { this.props.submit(this._pickedColor); }} /> |
| 155 | + </DialogFooter> |
| 156 | + </DialogContent>; |
| 157 | + } |
| 158 | + |
| 159 | + @autobind |
| 160 | + private _onColorChange(color: string): void { |
| 161 | + this._pickedColor = color; |
| 162 | + } |
| 163 | +} |
| 164 | +``` |
| 165 | +Add following class definition for our custom dialog under the just added class code. This one is the actual custom dialog, which will be called from the button click and which is inherited from the **BaseDialog**. |
| 166 | + |
| 167 | +```ts |
| 168 | +export default class ColorPickerDialog extends BaseDialog { |
| 169 | + public message: string; |
| 170 | + public colorCode: string; |
| 171 | + |
| 172 | + public render(): void { |
| 173 | + ReactDOM.render(<ColorPickerDialogContent |
| 174 | + close={ this.close } |
| 175 | + message={ this.message } |
| 176 | + defaultColor={ this.colorCode } |
| 177 | + submit={ this._submit } |
| 178 | + />, this.domElement); |
| 179 | + } |
| 180 | + |
| 181 | + public getConfig(): IDialogConfiguration { |
| 182 | + return { |
| 183 | + isBlocking: false |
| 184 | + }; |
| 185 | + } |
58 | 186 |
|
| 187 | + @autobind |
| 188 | + private _submit(color: string): void { |
| 189 | + this.colorCode = color; |
| 190 | + this.close(); |
| 191 | + } |
| 192 | +} |
59 | 193 | ```
|
60 |
| -code . |
| 194 | + |
| 195 | +## Associating custom dialog to button click |
| 196 | +To associate the custom dialog button to custom ListView Command Set, the code to initiate the dialog has to be added for the button click operation. |
| 197 | + |
| 198 | +In the code editor, open the **DialogDemoCommandSet.ts** file from **./src/extensions/dialogDemo/** folder. |
| 199 | + |
| 200 | +Add following import statements under the existing **strings** import. These are for using the just created custom dialog in the context of ListView Command Set. |
| 201 | + |
| 202 | +```ts |
| 203 | +import { Dialog } from '@microsoft/sp-dialog'; |
| 204 | +import ColorPickerDialog from './ColorPickerDialog'; |
| 205 | +``` |
| 206 | + |
| 207 | +Add following **_colorCode** variable definition above **onInit** function in the **DialogDemoCommandSet** class. This is used to store teh color picker dialog result. |
| 208 | + |
| 209 | +```ts |
| 210 | + private _colorCode: string; |
| 211 | +``` |
| 212 | + |
| 213 | +Update the **onExecute** function as follows. In this code we are doing following steps |
| 214 | + |
| 215 | +* Initiate custom dialog |
| 216 | +* Bypass message for the dialog, which will be used as title |
| 217 | +* Bypass color code for the dialog with default value, if not yet set |
| 218 | +* Show the custom dialog |
| 219 | +* Receive and store return value from the dialog |
| 220 | +* Show received value in out-of-the-box dialog using `Dialog.alert()` function |
| 221 | + |
| 222 | +```ts |
| 223 | + @override |
| 224 | + public onExecute(event: IListViewCommandSetExecuteEventParameters): void { |
| 225 | + switch (event.commandId) { |
| 226 | + case 'COMMAND_1': |
| 227 | + const dialog: ColorPickerDialog = new ColorPickerDialog(); |
| 228 | + dialog.message = 'Pick a color:'; |
| 229 | + // Use 'EEEEEE' as the default color for first usage |
| 230 | + dialog.colorCode = this._colorCode || '#EEEEEE'; |
| 231 | + dialog.show().then(() => { |
| 232 | + this._colorCode = dialog.colorCode; |
| 233 | + Dialog.alert(`Picked color: ${dialog.colorCode}`); |
| 234 | + }); |
| 235 | + break; |
| 236 | + default: |
| 237 | + throw new Error('Unknown command'); |
| 238 | + } |
| 239 | + } |
| 240 | +``` |
| 241 | + |
| 242 | +## Testing custom dialog in your tenant |
| 243 | +Move to **DialogDemoCommandSet.manifest.json** file in **./src/extensions/dialogDemo/** folder and copy **id** value, which will be used in the debug query parameter. |
| 244 | + |
| 245 | +Move to console side and execute following command. We use `--nobrowser` option, since local workbench cannot be currently used for debugging, so there's no reason to start that. |
| 246 | + |
| 247 | +```sh |
| 248 | +gulp serve --nobrowser |
| 249 | +``` |
| 250 | + |
| 251 | +This will start bundling and will serve the resulting manifest from `localhost` address. |
| 252 | + |
| 253 | + |
| 254 | + |
| 255 | +To test your extension, navigate to a site in your SharePoint Online tenant. |
| 256 | + |
| 257 | +Move to an existing custom list in the site with some items or create a new list and add few items to it for testing purposes. |
| 258 | + |
| 259 | +Append the following query string parameters to the URL. Notice that you will need to update the **id** to match your own extension identifier available from the **DialogDemoCommandSet.manifest.json** file: |
| 260 | + |
| 261 | +``` |
| 262 | +?loadSpfx=true&debugManifestsFile=https://localhost:4321/temp/manifests.js&customActions={"8701f44c-8c81-4e54-999d-62763e8f34d2":{"___location":"ClientSideExtension.ListViewCommandSet.CommandBar"}} |
| 263 | +``` |
| 264 | + |
| 265 | +Accept the loading of Debug Manifests by clicking **Load debug scripts** when prompted: |
| 266 | + |
| 267 | + |
| 268 | + |
| 269 | +Notice new button being visible in the toolbar of the list with test *Open Custom Dialog*. |
| 270 | + |
| 271 | + |
| 272 | + |
| 273 | +Click *Open Custom Dialog* button to see custom dialog rendered in the list view. |
| 274 | + |
| 275 | + |
| 276 | + |
| 277 | +Choose a color in the *Color Picker* and click **OK** to test how the code is returning selected value back to caller, which is then shown using out-of-the-box alert dialog. |
| 278 | + |
| 279 | + |
0 commit comments