Skip to content
Permalink
Browse files

Rewritten module using latest guidance

  • Loading branch information...
andrewconnell committed Nov 14, 2018
1 parent da083fe commit 758c07b69a3ed7c8169f9ad196c660a8d9f9e417
Showing with 38,224 additions and 1 deletion.
  1. +2 −0 .gitignore
  2. BIN 01 intro.pptx
  3. BIN 02 customprops.pptx
  4. BIN 03 pnpcontrols.pptx
  5. +25 −0 Demos/01-proppane/.editorconfig
  6. +32 −0 Demos/01-proppane/.gitignore
  7. +5 −0 Demos/01-proppane/.vscode/extensions.json
  8. +41 −0 Demos/01-proppane/.vscode/launch.json
  9. +13 −0 Demos/01-proppane/.vscode/settings.json
  10. +12 −0 Demos/01-proppane/.yo-rc.json
  11. +174 −0 Demos/01-proppane/README.md
  12. +18 −0 Demos/01-proppane/config/config.json
  13. +4 −0 Demos/01-proppane/config/copy-assets.json
  14. +7 −0 Demos/01-proppane/config/deploy-azure-storage.json
  15. +13 −0 Demos/01-proppane/config/package-solution.json
  16. +10 −0 Demos/01-proppane/config/serve.json
  17. +4 −0 Demos/01-proppane/config/write-manifests.json
  18. +7 −0 Demos/01-proppane/gulpfile.js
  19. +31 −0 Demos/01-proppane/package.json
  20. +1 −0 Demos/01-proppane/src/index.ts
  21. +28 −0 Demos/01-proppane/src/webparts/helloPropertyPane/HelloPropertyPaneWebPart.manifest.json
  22. +74 −0 Demos/01-proppane/src/webparts/helloPropertyPane/HelloPropertyPaneWebPart.module.scss
  23. +83 −0 Demos/01-proppane/src/webparts/helloPropertyPane/HelloPropertyPaneWebPart.ts
  24. +7 −0 Demos/01-proppane/src/webparts/helloPropertyPane/loc/en-us.js
  25. +10 −0 Demos/01-proppane/src/webparts/helloPropertyPane/loc/mystrings.d.ts
  26. +47 −0 Demos/01-proppane/teams/manifest.json
  27. BIN Demos/01-proppane/teams/tab20x20.png
  28. BIN Demos/01-proppane/teams/tab96x96.png
  29. +34 −0 Demos/01-proppane/tsconfig.json
  30. +30 −0 Demos/01-proppane/tslint.json
  31. +25 −0 Demos/02-custom-fields/.editorconfig
  32. +32 −0 Demos/02-custom-fields/.gitignore
  33. +5 −0 Demos/02-custom-fields/.vscode/extensions.json
  34. +41 −0 Demos/02-custom-fields/.vscode/launch.json
  35. +13 −0 Demos/02-custom-fields/.vscode/settings.json
  36. +12 −0 Demos/02-custom-fields/.yo-rc.json
  37. +179 −0 Demos/02-custom-fields/README.md
  38. +18 −0 Demos/02-custom-fields/config/config.json
  39. +4 −0 Demos/02-custom-fields/config/copy-assets.json
  40. +7 −0 Demos/02-custom-fields/config/deploy-azure-storage.json
  41. +13 −0 Demos/02-custom-fields/config/package-solution.json
  42. +10 −0 Demos/02-custom-fields/config/serve.json
  43. +4 −0 Demos/02-custom-fields/config/write-manifests.json
  44. +7 −0 Demos/02-custom-fields/gulpfile.js
  45. +17,553 −0 Demos/02-custom-fields/package-lock.json
  46. +35 −0 Demos/02-custom-fields/package.json
  47. +4 −0 ...-fields/src/controls/PropertyPaneContinentSelector/IPropertyPaneContinentSelectorInternalProps.ts
  48. +8 −0 ...2-custom-fields/src/controls/PropertyPaneContinentSelector/IPropertyPaneContinentSelectorProps.ts
  49. +55 −0 Demos/02-custom-fields/src/controls/PropertyPaneContinentSelector/PropertyPaneContentSelector.ts
  50. +62 −0 Demos/02-custom-fields/src/controls/PropertyPaneContinentSelector/components/ContinentSelector.tsx
  51. +9 −0 ...02-custom-fields/src/controls/PropertyPaneContinentSelector/components/IContinentSelectorProps.ts
  52. +5 −0 ...02-custom-fields/src/controls/PropertyPaneContinentSelector/components/IContinentSelectorState.ts
  53. +3 −0 Demos/02-custom-fields/src/controls/PropertyPaneContinentSelector/index.ts
  54. +1 −0 Demos/02-custom-fields/src/index.ts
  55. +28 −0 Demos/02-custom-fields/src/webparts/helloPropertyPane/HelloPropertyPaneWebPart.manifest.json
  56. +74 −0 Demos/02-custom-fields/src/webparts/helloPropertyPane/HelloPropertyPaneWebPart.module.scss
  57. +100 −0 Demos/02-custom-fields/src/webparts/helloPropertyPane/HelloPropertyPaneWebPart.ts
  58. +7 −0 Demos/02-custom-fields/src/webparts/helloPropertyPane/loc/en-us.js
  59. +10 −0 Demos/02-custom-fields/src/webparts/helloPropertyPane/loc/mystrings.d.ts
  60. +47 −0 Demos/02-custom-fields/teams/manifest.json
  61. BIN Demos/02-custom-fields/teams/tab20x20.png
  62. BIN Demos/02-custom-fields/teams/tab96x96.png
  63. +34 −0 Demos/02-custom-fields/tsconfig.json
  64. +30 −0 Demos/02-custom-fields/tslint.json
  65. +25 −0 Demos/03-pnp-controls/.editorconfig
  66. +32 −0 Demos/03-pnp-controls/.gitignore
  67. +5 −0 Demos/03-pnp-controls/.vscode/extensions.json
  68. +41 −0 Demos/03-pnp-controls/.vscode/launch.json
  69. +13 −0 Demos/03-pnp-controls/.vscode/settings.json
  70. +12 −0 Demos/03-pnp-controls/.yo-rc.json
  71. +195 −0 Demos/03-pnp-controls/README.md
  72. +19 −0 Demos/03-pnp-controls/config/config.json
  73. +4 −0 Demos/03-pnp-controls/config/copy-assets.json
  74. +7 −0 Demos/03-pnp-controls/config/deploy-azure-storage.json
  75. +13 −0 Demos/03-pnp-controls/config/package-solution.json
  76. +10 −0 Demos/03-pnp-controls/config/serve.json
  77. +4 −0 Demos/03-pnp-controls/config/write-manifests.json
  78. +7 −0 Demos/03-pnp-controls/gulpfile.js
  79. +17,593 −0 Demos/03-pnp-controls/package-lock.json
  80. +32 −0 Demos/03-pnp-controls/package.json
  81. +1 −0 Demos/03-pnp-controls/src/index.ts
  82. +26 −0 Demos/03-pnp-controls/src/webparts/helloWorld/HelloWorldWebPart.manifest.json
  83. +74 −0 Demos/03-pnp-controls/src/webparts/helloWorld/HelloWorldWebPart.module.scss
  84. +136 −0 Demos/03-pnp-controls/src/webparts/helloWorld/HelloWorldWebPart.ts
  85. +7 −0 Demos/03-pnp-controls/src/webparts/helloWorld/loc/en-us.js
  86. +10 −0 Demos/03-pnp-controls/src/webparts/helloWorld/loc/mystrings.d.ts
  87. +47 −0 Demos/03-pnp-controls/teams/manifest.json
  88. BIN Demos/03-pnp-controls/teams/tab20x20.png
  89. BIN Demos/03-pnp-controls/teams/tab96x96.png
  90. +34 −0 Demos/03-pnp-controls/tsconfig.json
  91. +30 −0 Demos/03-pnp-controls/tslint.json
  92. +13 −0 Demos/README.md
  93. BIN Images/EditPropPane-AddProps-01.png
  94. BIN Images/EditPropPane-AddProps-02.png
  95. BIN Images/EditPropPane-AddProps-03.png
  96. BIN Images/EditPropPane-AddProps-04.png
  97. BIN Images/EditPropPane-AddProps-05.png
  98. BIN Images/EditPropPane-CustomControl-01.png
  99. BIN Images/EditPropPane-PnPFieldCollection-01.png
  100. BIN Images/EditPropPane-PnPFieldCollection-02.png
  101. BIN Images/EditPropPane-PnPPeoplePicker-01.png
  102. BIN Images/EditPropPane-TestWP-01.png
  103. BIN Images/EditPropPane-TestWP-02.png
  104. BIN Images/EditPropPane-TestWP-03.png
  105. +575 −0 Lab.md
  106. +62 −0 LabFiles/components/ContinentSelector.tsx
  107. +9 −0 LabFiles/components/IContinentSelectorProps.ts
  108. +5 −0 LabFiles/components/IContinentSelectorState.ts
  109. +36 −1 README.md
@@ -59,3 +59,5 @@ typings/

# next.js build output
.next

.DS_Store
BIN +1.51 MB 01 intro.pptx
Binary file not shown.
BIN +1.72 MB 02 customprops.pptx
Binary file not shown.
BIN +1.53 MB 03 pnpcontrols.pptx
Binary file not shown.
@@ -0,0 +1,25 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org

root = true


[*]

# change these settings to your own preference
indent_style = space
indent_size = 2

# we recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

[{package,bower}.json]
indent_style = space
indent_size = 2
@@ -0,0 +1,32 @@
# Logs
logs
*.log
npm-debug.log*

# Dependency directories
node_modules

# Build generated files
dist
lib
solution
temp
*.sppkg

# Coverage directory used by tools like istanbul
coverage

# OSX
.DS_Store

# Visual Studio files
.ntvs_analysis.dat
.vs
bin
obj

# Resx Generated Code
*.resx.ts

# Styles Generated Code
*.scss.ts
@@ -0,0 +1,5 @@
{
"recommendations": [
"msjsdiag.debugger-for-chrome"
]
}
@@ -0,0 +1,41 @@
{
/**
* Install Chrome Debugger Extension for Visual Studio Code to debug your components with the
* Chrome browser: https://aka.ms/spfx-debugger-extensions
*/
"version": "0.2.0",
"configurations": [{
"name": "Local workbench",
"type": "chrome",
"request": "launch",
"url": "https://localhost:4321/temp/workbench.html",
"webRoot": "${workspaceRoot}",
"sourceMaps": true,
"sourceMapPathOverrides": {
"webpack:///../../../src/*": "${webRoot}/src/*",
"webpack:///../../../../src/*": "${webRoot}/src/*",
"webpack:///../../../../../src/*": "${webRoot}/src/*"
},
"runtimeArgs": [
"--remote-debugging-port=9222"
]
},
{
"name": "Hosted workbench",
"type": "chrome",
"request": "launch",
"url": "https://enter-your-SharePoint-site/_layouts/workbench.aspx",
"webRoot": "${workspaceRoot}",
"sourceMaps": true,
"sourceMapPathOverrides": {
"webpack:///../../../src/*": "${webRoot}/src/*",
"webpack:///../../../../src/*": "${webRoot}/src/*",
"webpack:///../../../../../src/*": "${webRoot}/src/*"
},
"runtimeArgs": [
"--remote-debugging-port=9222",
"-incognito"
]
}
]
}
@@ -0,0 +1,13 @@
// Place your settings in this file to overwrite default and user settings.
{
// Configure glob patterns for excluding files and folders in the file explorer.
"files.exclude": {
"**/.git": true,
"**/.DS_Store": true,
"**/bower_components": true,
"**/coverage": true,
"**/lib-amd": true,
"src/**/*.scss.ts": true
},
"typescript.tsdk": ".\\node_modules\\typescript\\lib"
}
@@ -0,0 +1,12 @@
{
"@microsoft/generator-sharepoint": {
"isCreatingSolution": true,
"environment": "spo",
"version": "1.7.0",
"libraryName": "hello-property-pane",
"libraryId": "dafd5b07-cc6b-4eb9-823e-0c914767ef1a",
"packageManager": "npm",
"isDomainIsolated": false,
"componentType": "webpart"
}
}
@@ -0,0 +1,174 @@
# DEMO: Working with the web part property pane

In this exercise, you will get hands-on experience in manipulating the property pane for a SPFx client-side web part in working with controls, groups and pages.

## Create a new SPFx Solution & Web Part

1. Open a command prompt and change to the folder where you want to create the project.
1. Run the SharePoint Framework Yeoman generator by executing the following command:

```shell
yo @microsoft/sharepoint
```

Use the following to complete the prompt that is displayed:

- **What is your solution name?:** HelloPropertyPane
- **Which baseline packages do you want to target for your component(s)?:** SharePoint Online only (latest)
- **Where do you want to place the files?:** Use the current folder
- **Do you want to allow the tenant admin the choice of being able to deploy the solution to all sites immediately without running any feature deployment or adding apps in sites?:** No
- **Will the components in the solution require permissions to access web APIs that are unique and not shared with other components in the tenant?:** No
- **Which type of client-side component to create?:** WebPart
- **What is your Web part name?:** HelloPropertyPane
- **What is your Web part description?:** HelloPropertyPane description
- **Which framework would you like to use?:** No JavaScript framework

1. Verify everything is working. Execute the following command to build, start the local web server and test the web part in the local workbench:

```shell
gulp serve
```

1. When the browser loads the local workbench, select the **Add a new web part** control...

![Screenshot of the SharePoint workbench](../../Images/EditPropPane-TestWP-01.png)

...and select the **HelloPropertyPane** web part to add the web part to the page:

![Screenshot of HelloPropertyPane web part in the SharePoint workbench](../../Images/EditPropPane-TestWP-02.png)

1. Select the **edit web part** control to the side of the web part to display the property pane:

![Screenshot of HelloPropertyPane's property pane](../../Images/EditPropPane-TestWP-03.png)

## Add New Properties to the web part

With a working web part, the next step is to customize the property pane experience.

1. Create two new properties that will be used in the web part and property pane:
1. Open the file **src\webparts\helloPropertyPane\HelloPropertyPaneWebPart.ts**
1. Locate the interface `IHelloPropertyPaneWebPartProps` after the `import` statements. Add the following two properties to the interface:

```ts
myContinent: string;
numContentsVisited: number;
```

1. Update the web part rendering to display the values of these two properties:
1. within the `HelloPropertyPaneWebPart` class, locate the `render()` method.
1. Within the `render()` method, locate the following line in the HTML output:

```html
<p class="${ styles.description }">${escape(this.properties.description)}</p>
```

1. Add the following two lines after the line you just located:

```html
<p class="${ styles.description }">Continent where I reside: ${escape(this.properties.myContinent)}</p>
<p class="${ styles.description }">Number of continents I've visited: ${this.properties.numContinentsVisited}</p>
```

At the moment the web part will render a blank string and undefined for these two fields as nothing is present in their values:

![Screenshot of HelloPropertyPane with no values](../../Images/EditPropPane-AddProps-01.png)

This can be addressed by setting the default values of properties when a web part is added to the page.

1. Set the default property values:
1. Open the file **src\webparts\helloPropertyPane\HelloPropertyPaneWebPart.manifest.json**
1. Locate the following section in the file: `preconfiguredEntries[0].properties.description`
1. Add a comma after the `description` property's value.
1. Add the following two lines after the `description` property:

```json
"myContinent": "North America",
"numContinentsVisited": 4
```

1. Updates to the web part's manifest file will not be picked up until you restart the local web server.
1. In the command prompt, press <kbd>CTRL+C</kbd> to stop the local web server.
1. Rebuild and restart the local web server by executing the command `gulp serve`.
1. When the SharePoint workbench loads, add the web part back tot he page to see the properties.

![Screenshot of HelloPropertyPane with no values](../../Images/EditPropPane-AddProps-02.png)

## Extend the Property Pane

Now that the web part has two new custom properties, the next step is to extend the property pane to allow users to edit the values.

1. Add a new text control to the property pane, connected to the **myContinent** property:
1. Open the file **src\webparts\helloPropertyPane\HelloPropertyPaneWebPart.ts**
1. Locate the method `getPropertyPaneConfiguration` & within it, locate the `groupFields` array.
1. Add a comma after the existing `PropertyPaneTextField()` call.
1. Add the following code after the comma:

```ts
PropertyPaneTextField('myContinent', {
label: 'Continent where I currently reside'
})
```

1. If the local web server is not running, start it by executing `gulp serve`.

Once the SharePoint workbench is running again, add the web part to the page and open the property pane.

Notice you can see the property and text box in the property pane. Any edits to the field will automatically update the web part:

![Screenshot of HelloPropertyPane with a new field](../../Images/EditPropPane-AddProps-03.png)

1. Now add a slider control to the property pane, connected to the **numContinentsVisited** property:
1. In the **HelloPropertyPaneWebPart.ts**, at the top of the file, add a `PropertyPaneSlider` reference to the existing `import` statement for the `@microsoft/sp-webpart-base` package.
1. Scroll down to the method `getPropertyPaneConfiguration` & within it, locate the `groupFields` array.
1. Add a comma after the last `PropertyPaneTextField()` call, add the following code:

```ts
PropertyPaneSlider('numContinentsVisited', {
label: 'Number of continents I\'ve visited',
min: 1, max: 6, showValue: true,
})
```

1. Notice the property pane now has a slider control to control the number of continents you have visited:

![Screenshot of HelloPropertyPane with a new field](../../Images/EditPropPane-AddProps-04.png)

## Add Control Validation

The previous steps added a slider control to allow the user to select 1-6 as the number of continents they have visited. But there are only five (5) continents... six is an invalid choice. Add validation logic to block this settings.

1. In the **HelloPropertyPaneWebPart.ts**, add the following method to the `HelloPropertyPaneWebPart` class. This method takes a string as an input and returns a string. This allows you to do custom validation logic. If this method returns an empty string, the value is considered valid; otherwise, the returned string is used as the error message.

```ts
private validateContinents(textboxValue: string): string {
const validContinentOptions: string[] = ['africa', 'antarctica', 'asia', 'north america', 'south america'];
const inputToValidate: string = textboxValue.toLowerCase();
return (validContinentOptions.indexOf(inputToValidate) === -1)
? 'Invalid continent entry; valid options are "Africa", "Antarctica", "Asia", "North America", and "South America"'
: '';
}
```

1. Wire the validation method to the text field control previously added.
1. Locate the text field that is associated with the **myContinent** property.
1. Add the following code to the options object passed into the `PropertyPaneTextField()` call as the second parameter: `onGetErrorMessage: this.validateContinents.bind(this)`.

The text field control should now look like the following code:

```ts
PropertyPaneTextField('myContinent', {
label: 'Continent where I currently reside',
onGetErrorMessage: this.validateContinents.bind(this)
}),
```

1. If the local web server is not running, start it by executing `gulp serve`.

Once the SharePoint workbench is running again, add the web part to the page and open the property pane.

1. Enter the name of a non-existent continent to test the validation logic:

![Screenshot of HelloPropertyPane with validation logic applied](../../Images/EditPropPane-AddProps-05.png)

Notice the property value is not updated when the control's input is invalid.
@@ -0,0 +1,18 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
"version": "2.0",
"bundles": {
"hello-property-pane-web-part": {
"components": [
{
"entrypoint": "./lib/webparts/helloPropertyPane/HelloPropertyPaneWebPart.js",
"manifest": "./src/webparts/helloPropertyPane/HelloPropertyPaneWebPart.manifest.json"
}
]
}
},
"externals": {},
"localizedResources": {
"HelloPropertyPaneWebPartStrings": "lib/webparts/helloPropertyPane/loc/{locale}.js"
}
}
@@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/copy-assets.schema.json",
"deployCdnPath": "temp/deploy"
}
@@ -0,0 +1,7 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/deploy-azure-storage.schema.json",
"workingDir": "./temp/deploy/",
"account": "<!-- STORAGE ACCOUNT NAME -->",
"container": "hello-property-pane",
"accessKey": "<!-- ACCESS KEY -->"
}
@@ -0,0 +1,13 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
"solution": {
"name": "hello-property-pane-client-side-solution",
"id": "dafd5b07-cc6b-4eb9-823e-0c914767ef1a",
"version": "1.0.0.0",
"includeClientSideAssets": true,
"isDomainIsolated": false
},
"paths": {
"zippedPackage": "solution/hello-property-pane.sppkg"
}
}
@@ -0,0 +1,10 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/core-build/serve.schema.json",
"port": 4321,
"https": true,
"initialPage": "https://localhost:5432/workbench",
"api": {
"port": 5432,
"entryPath": "node_modules/@microsoft/sp-webpart-workbench/lib/api/"
}
}
@@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/write-manifests.schema.json",
"cdnBasePath": "<!-- PATH TO CDN -->"
}
@@ -0,0 +1,7 @@
'use strict';

const gulp = require('gulp');
const build = require('@microsoft/sp-build-web');
build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`);

build.initialize(gulp);

0 comments on commit 758c07b

Please sign in to comment.
You can’t perform that action at this time.