Skip to content

Commit dbd9d2e

Browse files
committed
Updating baseline docs for 1.15 level
1 parent c3bc25e commit dbd9d2e

File tree

6 files changed

+250
-48
lines changed

6 files changed

+250
-48
lines changed

docs/spfx/compatibility.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ The following table lists SharePoint Framework and compatible versions of common
3434

3535
| SPFx | Node.js | NPM | TypeScript | React |
3636
| ------------------------------- | ------------------------ | ----------------------------------------- | -------------- | ----------- |
37+
| [1.15](release-1.15.md) | LTS v12, LTS v14 | v5, v6, v7, v8 | v4.5 | v16.13.1 |
3738
| [1.14](release-1.14.md) | LTS v12, LTS v14 | v5, v6 | v3.9 | v16.13.1 |
3839
| [1.13.1](release-1.13.1.md) | LTS v12, LTS v14 | v5, v6 | v3.9 | v16.13.1 |
3940
| [1.13.0](release-1.13.md) | LTS v12, LTS v14 | v5, v6 | v3.9 | v16.13.1 |

docs/spfx/extensions/get-started/building-form-customizer.md

Lines changed: 202 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
2-
title: Build your first Form customizer extension (preview)
2+
title: Build your first Form customizer extension)
33
description: Form customizers are SharePoint Framework components giving you an option to override the form experience in a list or library level by associating the component to the used content type.
4-
ms.date: 06/01/2022
4+
ms.date: 06/21/2022
55
ms.prod: sharepoint
66
ms.custom: scenarios:getting-started
77
---
@@ -11,7 +11,7 @@ ms.custom: scenarios:getting-started
1111
Form customizers are SharePoint Framework components giving you an option to override the form experience in a list or library level by associating the component to the used content type. Form customizer components can be used in SharePoint Online, and you build them using modern JavaScript tools and libraries.
1212

1313
>[!Important]
14-
> Form customizer will be released as part of the SharePoint Framework 1.15 which is currently still in preview status. See [v1.15 release notes](../../release-1.15.md) for details.
14+
> Form customizer were released as part of the SharePoint Framework 1.15, so ensure that you are using the right version in your environment. See [v1.15 release notes](../../release-1.15.md) for details.
1515
1616
## Create an extension project
1717

@@ -175,7 +175,205 @@ You can test and debug your Form Customizer within a live SharePoint Online site
175175
![List view with from customizer rendered with default outpu](../../../images/ext-forcustomizer-default-output.png)
176176

177177

178-
That's it. You have now created your first custom form component.
178+
## Add form item editing capabilities to the sample
179+
180+
Now that we have created the baseline component and tested that it works properly. We will be creating a separate rendering logic for display, edit and new forms and to support saving new items to the list.
181+
182+
1. Open the **./src/extensions/helloWorld/loc/myStrings.d.ts** file, and add new **Title** to the **IHelloWorldFormCustomizerStrings** interface . Interface should be as follows after your edits..
183+
184+
```typescript
185+
declare interface IHelloWorldFormCustomizerStrings {
186+
Save: string;
187+
Cancel: string;
188+
Close: string;
189+
Title: string;
190+
}
191+
```
192+
193+
1. Open the **./src/extensions/helloWorld/loc/en-us.js** file, and add new **Title** string to the file. File content should be as follows after your edits.
194+
195+
```typescript
196+
define([], function() {
197+
return {
198+
"Save": "Save",
199+
"Cancel": "Cancel",
200+
"Close": "Close",
201+
"Title": "Title"
202+
}
203+
});
204+
```
205+
206+
1. Open the **./src/extensions/helloWorld/HelloWorldFormCustomizer.module.scss** file, and update the styling definition as follows. We are adding error styling for the component.
207+
208+
```scss
209+
.helloWorld {
210+
background-color: "[theme:white, default:#ffffff]";
211+
color: "[theme:themePrimary, default:#0078d4]";
212+
padding: 0.5rem;
213+
214+
.error {
215+
color: red;
216+
}
217+
}
218+
```
219+
220+
1. Move to the top of the **HelloWorldFormCustomizer.ts** file.
221+
1. Locate the line `import styles from './HelloWorldFormCustomizer.module.scss';` and add the following lines immediately after it:
222+
223+
```typescript
224+
import { FormDisplayMode } from '@microsoft/sp-core-library';
225+
import {
226+
SPHttpClient,
227+
SPHttpClientResponse
228+
} from '@microsoft/sp-http';
229+
```
230+
231+
1. Include **_item** and **_etag** private types inside of the **HelloWorldFormCustomizer** class as shown in this code snippet. Notice that the class definition already exists in your code.
232+
233+
```typescript
234+
// This already exists in YOUR code
235+
export default class HelloWorldFormCustomizer
236+
extends BaseFormCustomizer<IHelloWorldFormCustomizerProperties> {
237+
238+
// Added for the item to show in the form; use with edit and view form
239+
private _item: {
240+
Title?: string;
241+
};
242+
// Added for item's etag to ensure integrity of the update; used with edit form
243+
private _etag?: string;
244+
```
245+
246+
1. Update the **onInit()** method as follows. This code is using **this.displayMode** to determine the status of the rendering and then fetches the selected list item if that's needed.
247+
248+
```typescript
249+
public onInit(): Promise<void> {
250+
if (this.displayMode === FormDisplayMode.New) {
251+
// we're creating a new item so nothing to load
252+
return Promise.resolve();
253+
}
254+
255+
// load item to display on the form
256+
return this.context.spHttpClient
257+
.get(this.context.pageContext.web.absoluteUrl + `/_api/web/lists/getbytitle('${this.context.list.title}')/items(${this.context.itemId})`, SPHttpClient.configurations.v1, {
258+
headers: {
259+
accept: 'application/json;odata.metadata=none'
260+
}
261+
})
262+
.then(res => {
263+
if (res.ok) {
264+
// store etag in case we'll need to update the item
265+
this._etag = res.headers.get('ETag');
266+
return res.json();
267+
}
268+
else {
269+
return Promise.reject(res.statusText);
270+
}
271+
})
272+
.then(item => {
273+
this._item = item;
274+
return Promise.resolve();
275+
});
276+
}
277+
```
278+
279+
1. Update the **render()** method as follows. Render the form either in display only or in the edit mode, depending on the display mode of the form. In this case we use the same renderig for new and edit experience, but you could easily have dedicated option if needed.
280+
281+
```typescript
282+
public render(): void {
283+
// render view form
284+
if (this.displayMode === FormDisplayMode.Display) {
285+
286+
this.domElement.innerHTML =
287+
`<div class="${styles.basics}">
288+
<label for="title">${strings.Title}</label>
289+
<br />
290+
${this._item?.Title}
291+
<br />
292+
<br />
293+
<input type="button" id="cancel" value="${strings.Close}" />
294+
</div>`;
295+
296+
document.getElementById('cancel').addEventListener('click', this._onClose.bind(this));
297+
}
298+
// render new/edit form
299+
else {
300+
this.domElement.innerHTML =
301+
`<div class="${styles.basics}">
302+
<label for="title">${strings.Title}</label><br />
303+
<input type="text" id="title" value="${this._item?.Title || ''}"/>
304+
<br />
305+
<br />
306+
<input type="button" id="save" value="${strings.Save}" />
307+
<input type="button" id="cancel" value="${strings.Cancel}" />
308+
<br />
309+
<br />
310+
<div class="${styles.error}"></div>
311+
</div>`;
312+
313+
document.getElementById('save').addEventListener('click', this._onSave.bind(this));
314+
document.getElementById('cancel').addEventListener('click', this._onClose.bind(this));
315+
}
316+
}
317+
```
318+
319+
1. Update the **_onSave** methods in the the **HelloWorldFormCustomizer** class as follows.
320+
321+
```typescript
322+
private _onSave = async (): Promise<void> => {
323+
// disable all input elements while we're saving the item
324+
this.domElement.querySelectorAll('input').forEach(el => el.setAttribute('disabled', 'disabled'));
325+
// reset previous error message if any
326+
this.domElement.querySelector(`.${styles.error}`).innerHTML = '';
327+
328+
let request: Promise<SPHttpClientResponse>;
329+
const title: string = (document.getElementById('title') as HTMLInputElement).value;
330+
331+
switch (this.displayMode) {
332+
case FormDisplayMode.New:
333+
request = this._createItem(title);
334+
break;
335+
case FormDisplayMode.Edit:
336+
request = this._updateItem(title);
337+
}
338+
339+
const res: SPHttpClientResponse = await request;
340+
341+
if (res.ok) {
342+
// You MUST call this.formSaved() after you save the form.
343+
this.formSaved();
344+
}
345+
else {
346+
const error: { error: { message: string } } = await res.json();
347+
348+
this.domElement.querySelector(`.${styles.error}`).innerHTML = `An error has occurred while saving the item. Please try again. Error: ${error.error.message}`;
349+
this.domElement.querySelectorAll('input').forEach(el => el.removeAttribute('disabled'));
350+
}
351+
}
352+
```
353+
354+
1. Add new method **_createItem** to the **HelloWorldFormCustomizer** class.
355+
356+
```typescript
357+
private _createItem(title: string): Promise<SPHttpClientResponse> {
358+
return this.context.spHttpClient
359+
.post(this.context.pageContext.web.absoluteUrl + `/_api/web/lists/getByTitle('${this.context.list.title}')/items`, SPHttpClient.configurations.v1, {
360+
headers: {
361+
'content-type': 'application/json;odata.metadata=none'
362+
},
363+
body: JSON.stringify({
364+
Title: title
365+
})
366+
});
367+
}
368+
```
369+
370+
1. Add new method **_updateItem** to the **HelloWorldFormCustomizer** class.
371+
372+
```typescript
373+
374+
```
375+
376+
Now the code is complete to support minimal New, Edit and Display experiences and you can test out the different experiences using different configurations for debugging.
179377

180378
## Deployment of your extension
181379

docs/spfx/release-1.15.md

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,24 @@
11
---
2-
title: SharePoint Framework v1.15 preview release notes
3-
description: Release notes for the SharePoint Framework v1.15 preview release
4-
ms.date: 06/07/2022
2+
title: SharePoint Framework v1.15 release notes
3+
description: Release notes for the SharePoint Framework v1.15 release
4+
ms.date: 06/21/2022
55
ms.prod: sharepoint
66
ms.localizationpriority: high
77
---
8-
# SharePoint Framework v1.15 preview release notes
8+
# SharePoint Framework v1.15 release notes
99

10-
There will be multiple public preview release using the @next tag in the NPMJS.org registry before final release candidates and a final public release.
10+
This release introduces updates across the features around Microsoft Viva, Microsoft Teams and SharePoint.
1111

12-
[!INCLUDE [spfx-release-beta](../../includes/snippets/spfx-release-beta.md)]
13-
14-
- rc.0 **Released:** June 1, 2022
15-
- beta.6 **Released:** April 19, 2022
16-
- beta.1 **Released:** March 8, 2022
12+
**Released:** June 21, 2022
1713

1814
[!INCLUDE [spfx-release-notes-common](../../includes/snippets/spfx-release-notes-common.md)]
1915

20-
## Install the latest preview release
16+
## Install the latest released version
2117

22-
Install the latest preview release of the SharePoint Framework (SPFx) by including the **@next** tag:
18+
Install the latest release of the SharePoint Framework (SPFx) by including the **@latest** tag:
2319

2420
```console
25-
npm install @microsoft/generator-sharepoint@next --global
21+
npm install @microsoft/generator-sharepoint@latest --global
2622
```
2723

2824
## Upgrading projects from v1.14 to v1.15
@@ -34,10 +30,10 @@ npm install @microsoft/generator-sharepoint@next --global
3430
npm uninstall @microsoft/{spfx-package-name}@1.14
3531
```
3632

37-
2. Install the new v1.15 preview package:
33+
2. Install the new v1.15 package:
3834

3935
```console
40-
npm install @microsoft/{spfx-package-name}@next --save --save-exact
36+
npm install @microsoft/{spfx-package-name}@latest --save --save-exact
4137
```
4238

4339
[!INCLUDE [spfx-release-upgrade-tip](../../includes/snippets/spfx-release-upgrade-tip.md)]
@@ -46,46 +42,49 @@ npm install @microsoft/generator-sharepoint@next --global
4642

4743
### Form Customizer Extension
4844

49-
The Form Customizer Extension allows developers to customize new, edit and display forms of the lists and document libraries.
45+
The Form Customizer Extension allows developers to customize new, edit and display forms of the lists and document libraries.
5046

5147
* [Tutorial on creating your first form customizer](extensions/get-started/building-form-customizer.md)
5248

5349
> [!NOTE]
54-
> The API to apply form customizers to a content type or list is still work in progress.
55-
> Developers can use local debugging and direct link to `SPListForm.aspx` page to test the customizers.
56-
> Please, check `config\serve.json` file created during the provisioning for more details.
57-
> You can see live demo of this process from following YouTube video - [Preview on upcoming list extensibility options with SPFx v1.15](https://www.youtube.com/watch?v=90DWB9hjo-k).
50+
> You can see live demo of this feature from the following YouTube video - [Getting started on building custom list form components with SPFx v1.15](https://www.youtube.com/watch?v=LF5eQHBx10o).
51+
52+
53+
### Node.js v16 Support
54+
55+
SharePoint Framework solutions now support Node.js v16 as the default Node.js version.
56+
5857

5958
### Microsoft Graph JavaScript SDK v3 Support
6059

6160
The **MSGraphClientFactory** allows a developer to select the version of the Microsoft Graph JavaScript SDK to use.
6261

6362
> [!NOTE]
64-
> Default behavior is to use v1 of the Microsoft Graph JavaScript SDK for backward compatibility.
63+
> Starting with SPFx 1.15 only v3 of the Microsoft Graph JavaScript SDK is supported. v1 support is removed for all new and updated solutions. Please update your code accordingly to get the right version.
6564

6665
```typescript
6766
this.context.msGraphClientFactory.getClient('3');
6867
```
6968

7069
### TypeScript v4 Support
7170

72-
SPFx solutions now support TypeScript v4.5
71+
SharePoint Framework solutions now support TypeScript v4.5
7372

7473
### ESLint Support
7574

76-
SPFx solutions now support ESLint 8.3.0 instead of deprecated TSLint.
75+
SPFx solutions now support [ESLint](https://github.com/typescript-eslint/typescript-eslint) 8.x instead of the deprecated [TSLint](https://github.com/palantir/tslint).
7776

7877
### Updated Microsoft Teams JavaScript Client SDK
7978

80-
SPFx solutions now support Microsoft Teams JavaScript Client SDK v1.12.1.
79+
SharePoint Framework solutions now support [Microsoft Teams JavaScript Client SDK v1.12.1](https://github.com/OfficeDev/microsoft-teams-library-js).
8180

8281
### Updated Command Set Extension Template
8382

8483
The template was updated to use `listViewStateChanged` event instead of deprecated `onListViewUpdated` event.
8584

8685
### Changes to Scaffolding Options and Prompts
8786

88-
- new command line option: `--use-heft`. If specified, the solution will build the project using Heft.
87+
- new command line option: `--use-heft`. If specified, the solution will build the project using [Heft](https://rushstack.io/pages/heft/overview/).
8988

9089
## Deprecations
9190

@@ -95,19 +94,22 @@ The template was updated to use `listViewStateChanged` event instead of deprecat
9594

9695
### February & March Timeframe
9796

98-
- [#7827](https://github.com/SharePoint/sp-dev-docs/issues/7827) - `deploy-azure-storage` command always creates container with Pubic Access Level of 'Private' instead of Blob
99-
- [#7826](https://github.com/SharePoint/sp-dev-docs/issues/7826) - [SPFx 1.15.0-beta.1] package-solution fails when elements.xml file is referenced from external folder and sharepoint/assets doesn't exist
100-
- [#6477](https://github.com/SharePoint/sp-dev-docs/issues/6477) - Subscribe to list notifications with transport error
101-
- [#7845](https://github.com/SharePoint/sp-dev-docs/issues/7845) - `command.disabled` not always respected
102-
- [#6807](https://github.com/SharePoint/sp-dev-docs/issues/6807) - SharePoint spfx webparts seem to be taking up all sessionStorage in the browser
103-
- [#7684](https://github.com/SharePoint/sp-dev-docs/issues/7684) - SPFx app inside Microsoft Teams authentication error (sso-getAdalSsoToken-receive)
104-
- [#7739](https://github.com/SharePoint/sp-dev-docs/issues/7739) - CommandSet Extensions don't work in Document Library when navigating from LHN link on site home page
105-
- [#7794](https://github.com/SharePoint/sp-dev-docs/issues/7794) - `listViewStateChangedEvent` does not trigger for grouped list views
106-
- [#7805](https://github.com/SharePoint/sp-dev-docs/issues/7805) - SPFx is loading library component old version for some users
107-
- [#7795](https://github.com/SharePoint/sp-dev-docs/issues/7795) - `this.context.pageContext.list.serverRelativeUrl` doesn't refresh
10897
- [#7680](https://github.com/SharePoint/sp-dev-docs/issues/7680) - Theme colors do not load (immediately) on SP listpage or site contents page
10998
- [#6403](https://github.com/SharePoint/sp-dev-docs/issues/6403) - DynamicData.tryGetValue() should not fail if disposed
11099
- [#5979](https://github.com/SharePoint/sp-dev-docs/issues/5979) - Problem popup when remove SPFx Teams Tab
111100
- [#7679](https://github.com/SharePoint/sp-dev-docs/issues/7679) - Field customizer doesn't load consistently when searching
112101
- [#7689](https://github.com/SharePoint/sp-dev-docs/issues/7689) - [SPFx-Heft-Plugins][SPFx 1.13.1] elementManifests path resolving differently on Windows and Linux when referencing external file path
113102
- [#7771](https://github.com/SharePoint/sp-dev-docs/issues/7771) - SPFx v1.14.0: Image Helper API, exception in btoa, string contains characters outside of the Latin1 range
103+
- [#7684](https://github.com/SharePoint/sp-dev-docs/issues/7684) - SPFx app inside Microsoft Teams authentication error (sso-getAdalSsoToken-receive)
104+
- [#7739](https://github.com/SharePoint/sp-dev-docs/issues/7739) - CommandSet Extensions don't work in Document Library when navigating from LHN link on site home page
105+
- [#7794](https://github.com/SharePoint/sp-dev-docs/issues/7794) - `listViewStateChangedEvent` does not trigger for grouped list views
106+
- [#7805](https://github.com/SharePoint/sp-dev-docs/issues/7805) - SPFx is loading library component old version for some users
107+
- [#7795](https://github.com/SharePoint/sp-dev-docs/issues/7795) - `this.context.pageContext.list.serverRelativeUrl` doesn't refresh
108+
- [#7827](https://github.com/SharePoint/sp-dev-docs/issues/7827) - `deploy-azure-storage` command always creates container with Pubic Access Level of 'Private' instead of Blob
109+
- [#7826](https://github.com/SharePoint/sp-dev-docs/issues/7826) - [SPFx 1.15.0-beta.1] package-solution fails when elements.xml file is referenced from external folder and sharepoint/assets doesn't exist
110+
- [#6477](https://github.com/SharePoint/sp-dev-docs/issues/6477) - Subscribe to list notifications with transport error
111+
- [#7845](https://github.com/SharePoint/sp-dev-docs/issues/7845) - `command.disabled` not always respected
112+
- [#6807](https://github.com/SharePoint/sp-dev-docs/issues/6807) - SharePoint spfx webparts seem to be taking up all sessionStorage in the browser
113+
- [#7950](https://github.com/SharePoint/sp-dev-docs/issues/7950) - `globalDependecies` in `config.json` don't work
114+
- [#7949](https://github.com/SharePoint/sp-dev-docs/issues/7949) - `command.disabled` still not working
115+
- [#7974](https://github.com/SharePoint/sp-dev-docs/issues/7974) - Property `folderInfo` is undefined if folder is loaded directly

0 commit comments

Comments
 (0)