Hi all,
I just pushed my last code contribution on GitHub, here you can find full code solution.
Update: Source code is also available on the official GitHub of Microsoft SharePoint PnP
https://github.com/SharePoint/sp-dev-fx-extensions/tree/master/samples/react-command-page-model-pnpjs
PnP/PnPjs is an
The awesome aspect of this library is that it is possible to call the SharePoint
Seen all this, I wrote an SPFx extension using @pnp/sp that allow creating Modern Pages based on prefilled modern pages marked as “Page Model”, inside the Site Pages Library, and code defined pages. Users can select a Modern page as a model just setting a custom property page named “Is Template” to “Yes”.
General needs
People often need to create periodically editorial pages with the same composition, sections structure and
- Employee of the month
- Weekly post from General Manager
- New hires list
This SPFX extension allows users to define their own page models and reuse them easily, without export page template with PnP but directly in the Modern Team Site.
Prerequisites
You need to add a Choice (yes/no) Site Column to Page Library named “Is Template” to “Site Page” Content Type
How to set a Modern Page as Page Model
And finally… Modern Page Model with PnP/PnPjs in action
Code deep-dive
The solution is pushed in my GitHub repository, but I would like to focus on two snippets
How to copy a Modern Page from an existing page
const templatePage = await ClientSidePage.fromFile(sp.web.getFileByServerRelativeUrl(templatePageUrl)); await templatePage.copyPage(sp.web, pagename + ".aspx", pagename, false);
Define your own ClientSideWebpartPropertyTypes namespace (optional)
import { ClientSideText, ClientSideWebpart, sp, ClientSidePage } from "@pnp/sp"; export declare namespace MyClientSideWebpartPropertyTypes { /** * Properties for People (component id: 7f718435-ee4d-431c-bdbf-9c4ff326f46e) */ interface People { layout: "1" | "2"; persons?: any[]; } }
Create a Modern Page with PnP/PnPjs using your own ClientSideWebpartPropertyTypes
const page = await sp.web.addClientSidePage(pagename + ".aspx"); const partDefs = await sp.web.getClientSideWebParts(); const section = page.addSection(); const column1 = section.addColumn(4); // find the definition we want, here by id const partDef = partDefs.filter(c => c.Id === "7f718435-ee4d-431c-bdbf-9c4ff326f46e"); // optionally ensure you found the def if (partDef.length < 1) { // we didn't find it so we throw an error console.log('ops'); throw new Error("Could not find the web part"); } // create a ClientWebPart instance from the definition const part = ClientSideWebpart.fromComponentDef(partDef[0]); part.setProperties<MyClientSideWebpartPropertyTypes.People>({ layout: "2", persons: [ { "id": "i:0#.f|membership|jsmith@federicoporceddu.onmicrosoft.com", "upn": "jsmith@federicoporceddu.onmicroosft.com", "role": "", "department": "", "phone": "", "sip": "" } ] }); // add a text control to the second new column column1.addControl(part); const column2 = section.addColumn(8); //// add a text control to the second new column column2.addControl(new ClientSideText("Lorem ipsum dolor sit amet"); page.disableComments(); await page.save();
In 1.3.0 version pnp/pnpjs team introduce ClientSidePage copyPage extension method, so you need to use this version or a major.
Future improvements
With this sample, I would like to show how it is easy work with PnP/PnPjs, but ovviously it is not a full solution. In the future I will add this features
- Deploy “Is Template” site column as an asset from this SPFx extension solution
- Hide pages models from search results
- Host pages models in a different site/library in order to share them cross-site or just for isolate site pages from a “site template”
Hope you enjoy my new code contribution!
Cheers
Federico
[…] Modern Page Model with PnP/PnPjs – Federico Porceddu (Avanade) […]
[…] about this, I was mentionend during the SharePoint Dev Weekly – Episode 32 with my small sample Modern Page Model with PnP/PnPjs thanks to Vesa and Waldek […]
[…] Frederico’s demo solution in GitHub | Blog post […]
Thank you for sharing Federico , i am studying your code and its helping me allot.
I wonder if you could help me to find the IDs of the webparts in SharePoint online (like the one u added {people webpart}) and how to set their properties ?
I tried to search about it but no result.
Hi Ahmad!
Thank you for your comment 🙂
If you need to get all the manifest details of the ClientWebparts deployed, you can use _api/web/GetClientSideWebParts rest API: it returns the list of ClientWebparts (uploaded to the appcatalog) with the manifest details.
It is already wrapped in PnpJs with
Let me know if it helps 🙂
Cheers!
Federico
I’t only run on sharepoint online, sharepoint on premise 2019 not working, I tried
Hi Binh,
yes this version is a sample, it works only on SharePoint online.
If you want, you can migrate to SharePoint 2019 / on-premise, reworking code and use the same approach.
Cheers!
Federico