How To Create a Copy Of Site Page And Update Property Of The Web Parts

Introduction

 
In this article, we will learn how to copy a site page and update the property of web parts while creating a copy of the site page.
 

How to create a copy of the page

 
Step 1
First, we need to install SharePoint Patterns and Practices client-side libraries.
 
Use the below command to install the PNP package in your react spfx solution,
 
npm i @pnp/sp
 
Step 2
 
We will need the current context of the page. So, make sure you have defined the property of context and it has an assigned value as this.context as shown below:
  1. export interface ICopyPageProps {  
  2.    description: string;  
  3.    context: any;  
  4. }   
We can assigna  value to property as in the below code,
  1. const element: React.ReactElement<ICopyPageProps> = React.createElement(  
  2. CopyPage,  
  3.    {  
  4.       description: this.properties.description,  
  5.       context: this.context  
  6.    }  
  7. );  
Step 3
 
Now we need to import the library into our SPFx web part and access the root sp object and other methods of client-side pages like @pnp/sp, @pnp/sp/webs, @pnp/sp/clientside-pages.
  1. import { sp } from "@pnp/sp";  
  2. import "@pnp/sp/webs";  
  3. import { ClientsidePageFromFile, IClientsidePage, ClientsideWebpart  
  4. } from "@pnp/sp/clientside-pages";  
Step 4
 
Now we need the URL of the source page, from which page we want to create a copy of the page. We will store the URL of the source page in a variable.
  1. var sourcePageURL = “https://****.sharepoint.com/sites/Test/SitePages/sourcepage.aspx”;  
Step 5
 
Now we will get the template of the source page from the url as below:
  1. const pageTemplate = await ClientsidePageFromFile(sp.web.getFileByServerRelativePath(sourcePageURL));  
Step 6
 
Now we will generate the copy of the source page using the copy method. Copy method will have 4 parameters,
 
copy(web: IWeb, pageName: string, title: string, publish?: boolean, promotedState?: PromotedState): Promise<IClientsidePage>
  • web: The web where we will create the copy
  • pageName: The file name of the new page
  • title: The title of the new page
  • publish: If true the page will be published
Below is an example of how to use copy method:
  1. const newPage = await pageTemplate.copy(sp.web, “Page Name”, “Page Title”, false);  
Step 7
 
Using the copy method, a copy of the page will be created. Now we need to save this new page.
 
To save this new page, we need to use save method of pnp client side pages library. Save method has one parameter which has boolean value.
save(publish?: boolean): Promise<boolean>
 
If true the page is published, if false the changes are persisted to SharePoint but not published [Default: true]
 
Now a copy of the page is created.
 
It will create a copy page without updating any property of your web part.
 
If you want to update a property while creating a copy of the page use the below steps.
 

How to update the property of web parts while creating a copy of page

 
Step 1
 
After creating a copy and before saving the page, you need to get an instance of all web parts of the new page.
 
To get this, use the below method,
  1. let WebpartPageWebpartInstance: string[] = this.getPageCustomWebPartsInstances(newPage);  
The above line of code will give you array of all web parts of the seleced page.
 
Step 2
 
Now we will use loop 'for each' on the instance of the page which we get from step 1.
 
And in this loop we will get the property and we can update any property which you want to update. Here in the below code I am updating Category property. So, if there is Category property in any of the web parts it will update it to Accounts,
  1. WebpartPageWebpartInstance.forEach(webpartInstanceId => {  
  2.             const currentWebpart: ClientsideWebpart = newPageDraft.findControl((c) => c.id === webpartInstanceId);  
  3.             let currentProps: any = howToControl.getProperties();  
  4.             if (currentProps.Category != undefined) {  
  5.                 currentProps.Category = “Accounts”;  
  6.             }  
  7.         }  
Step 3
 
After this loop, you can save your page using the page. save method.
 
Below is the full code snippet for all the processes. In this code I am updating the value of the category property. You can also update multiple properties of the web part. Make sure that the property name is case sensitive.
  1. public async copyAndUpdateProperty(currentObj) {  
  2.     var selectedPage = currentObj.state.selectedPage;  
  3.     var currentContext: any = currentObj.props.context;  
  4.     var siteUrl = currentContext.pageContext.web._serverRelativeUrl;  
  5.     var sourcePageUrl = siteUrl + "/SitePages/" + selectedPage;  
  6.     if (selectedPage != "Select" && this.state.category != "Select" && this.state.title != "" && this.state.name != "") {  
  7.         this.setState({  
  8.             isLoading: true  
  9.         });  
  10.         var siteUrl = currentContext.pageContext.web._serverRelativeUrl;  
  11.         var sourcePageUrl = siteUrl + "/SitePages/" + selectedPage;  
  12.         const pageTemplate = await ClientsidePageFromFile(sp.web.getFileByServerRelativePath(sourcePageUrl));  
  13.         const newPageDraft = await pageTemplate.copy(sp.web, this.state.title, this.state.name, false);  
  14.         const howToWebpartId = "E8DFA76D-1752-46CB-9844-AADF4D18F698";  
  15.         let howToWebpartPageWebpartInstanceId: string[] = this.getPageCustomWebPartInstanceIdByWebpartId(howToWebpartId.toLowerCase(), newPageDraft);  
  16.         howToWebpartPageWebpartInstanceId.forEach(webpartInstanceId => {  
  17.             const howToControl: ClientsideWebpart = newPageDraft.findControl((c) => c.id === webpartInstanceId);  
  18.             //update properties as needed... this should be a typed object to make it easier...  
  19.             let currentProps: any = howToControl.getProperties();  
  20.             currentProps.Category = this.state.category;  
  21.         });  
  22.         newPageDraft.save(true);  
  23.         alert("Page copied successfully");  
  24.         this.setState({  
  25.             isLoading: false  
  26.         });  
  27.     } else {  
  28.         alert("Please select all values");  
  29.     }  
  30. }  
  31. private getPageCustomWebPartInstanceIdByWebpartId(webpartId: string, page: IClientsidePage): string[] {  
  32.     const instances: string[] = [];  
  33.     page.sections.forEach(section => {  
  34.         section.columns.forEach(column => {  
  35.             column.controls.forEach(control => {  
  36.                 if (control.data.webPartId == webpartId) {  
  37.                     instances.push(control.id);  
  38.                 }  
  39.             });  
  40.         });  
  41.     });  
  42.     return instances;  
  43. }  
Now your new page will have updated properties.
 
I hope this blog will be helpful to you.