SharePoint Online – How to pass parameters to SPFx extension by creating a WebPart interface.
Hope you have basic understanding of SPFx extension application customizer. If not I would suggest you to go through this link to understand basic on SPFx extension.
In this article we have learned how to disable automatic enabling of SPFx extension when app is installed. Now you might have to give user option to enable it manually.
Hello world example provide by microsoft on application customizer by using placeholder is that you would need to hard code html in code itself which you want to show on pages. If there is slight change in html, you might have to upload new version of app.
This scenarios can come when you want to pass parameters to SPFx extension by taking input from user. Suppose you want to add custom header or footer to Sharepoint modern page but you want to give admin a interface to provide html of his choice and then pass it to SPFx extension application customizer to add it on top or bottom.
My idea was here to provide configuration option to site admin/users to provide there custom html. To do this we would have to combine webpart and extension in Single package. I have created running solution of this for others to use..
Few points to understand
- application customizer are added to site using custom action.
- An association is created between custom action and application customizer.
- To enable application customizer manually, we need to create a user custom action.
- Below 3 properties of custom action will associate it to application customizer.
- Location – it value should be ‘ClientSideExtension.ApplicationCustomizer’, based on on extension type.
- ClientSideComponentId – this should be id of you application customizer, this id you can get from applicationcustomizer.manifest.json. Copy the id attribute value.
- ClientSideComponentProperties – this is where you can pass your custom properties value in json as string.
- Once you add custom action via rest api with above attributes. It will create custom action and also enable your extension.
As per this example what we will do is create a web part inside same solution(having extension). Within webpart added a simple input text area and button. On click of button setCustomAction method is called.
Below are some code snippets for your reference.
protected setCustomAction() { try { var title = 'SettingHeaderFooterwithAppCustomizer'; var description = 'This user action is of type application customizer to add header footer or custom javascript via SFPx extension'; var headtext = document.getElementById("headerText")["value"] ; this._getdigest() .then((digrestJson) => { console.log(digrestJson); const digest = digrestJson.FormDigestValue; const payload = JSON.stringify({ Location: 'ClientSideExtension.ApplicationCustomizer', Title: title, Description: description, ClientSideComponentId: 'fc14316e-72db-4860-8283-458154eaef3e', ClientSideComponentProperties: JSON.stringify({myprop:headtext }), }); const headers = { 'X-RequestDigest': digest, "content-type": "application/json;odata=verbose", }; const spOpts: ISPHttpClientOptions = { body:payload }; this.context.spHttpClient.post(this.context.pageContext.web.absoluteUrl + `/_api/site/UserCustomActions`, SPHttpClient.configurations.v1,spOpts) .then((response: SPHttpClientResponse) => { console.log( response.json()); }); }); } catch (error) { console.error(error); } }
Get digest method to get digest value for POST method
private _getdigest(): Promise<any> { const spOpts: ISPHttpClientOptions = { }; return this.context.spHttpClient.post(this.context.pageContext.web.absoluteUrl + `/_api/contextinfo`, SPHttpClient.configurations.v1,spOpts) .then((response: SPHttpClientResponse) => { return response.json(); }); }
Render method to show how to add textarea and button
public render(): void { /* this.domElement.innerHTML = ` <div class="${ styles.wpConfigureApplicationCustomizer }"> <div class="${ styles.container }"> <div class="${ styles.row }"> <div class="${ styles.column }"> <span class="${ styles.title }">Welcome to SharePoint!</span> <p class="${ styles.subTitle }">Customize SharePoint experiences using Web Parts.</p> <p class="${ styles.description }">${escape(this.properties.description)}</p> <a href="https://aka.ms/spfx" class="${ styles.button }"> <span class="${ styles.label }">Learn more</span> </a> </div> </div> </div> </div>`;*/ this.domElement.innerHTML += '<textarea id ="headerText" rows = "5" cols = "50" name = "description">Enter Header HTML</textarea>'; this.domElement.innerHTML += '<button type="button" id="btnRegister">Click Me!</button>'; this._setButtonEventHandlers(); }
Method to bind click event of button(yes this is how we have to do it)
private _setButtonEventHandlers(): void { const webPart: WpConfigureApplicationCustomizerWebPart = this; this.domElement.querySelector('#btnRegister').addEventListener('click', () => { //this.getData(); this.setCustomAction(); }); }
Also make sure you remove custom actions before adding new one, because SharePoint will create custom actions on every button click and it would start adding n many html instance of header/footer.
I won’t go in detail on how to read this parameters in Extension but you can read this parameters as ‘this.properties.myprop’ in Extensionfile.ts.