1

I am trying to achieve this using SPFx web part:

  1. The web part will provide a Button and a Text field.

  2. The user add the Web Part >> edit it >> enter the text inside the text field (inside the setting page) >> save the web part>> then the web part will render a button >> if the user clicks on the button a popup will be shown with the entered text.

Now I found this link, Mode pop up In SPFx which almost achieves what I am looking for, except that the Popup text inside the example is been hard-coded inside the .tsx file.

So, what are the steps to make the Popup text configurable inside the web part settings instead of been hard-coded?

Here is my ReactPortalWebPart.ts file:

import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version } from '@microsoft/sp-core-library';
import {
  IPropertyPaneConfiguration,
  PropertyPaneTextField
} from '@microsoft/sp-property-pane';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';

import * as strings from 'ReactPortalWebPartStrings';
import ReactPortal from './components/ReactPortal';
import { IReactPortalProps } from './components/IReactPortalProps';

export interface IReactPortalWebPartProps {
  description: string;
}

export default class ReactPortalWebPart extends BaseClientSideWebPart<IReactPortalWebPartProps> {

  public render(): void {
    const element: React.ReactElement<IReactPortalProps> = React.createElement(
      ReactPortal,
      {
        description: this.properties.description
      }
    );

    ReactDom.render(element, this.domElement);
  }

  protected onDispose(): void {
    ReactDom.unmountComponentAtNode(this.domElement);
  }

  protected get dataVersion(): Version {
    return Version.parse('1.0');
  }

  protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
    return {
      pages: [
        {
          header: {
            description: strings.PropertyPaneDescription
          },
          groups: [
            {
              groupName: strings.BasicGroupName,
              groupFields: [
                PropertyPaneTextField('description', {
                  label: strings.DescriptionFieldLabel
                })
              ]
            }
          ]
        }
      ]
    };
  }
}

and here is the ReactPortal.tsx:

import * as React from 'react';  
    import { IReactPortalProps } from './IReactPortalProps';  
    import Myportal from "./Myportal";  
    export default class ReactPortal extends React.Component<IReactPortalProps, {}> {  
      public render(): React.ReactElement<IReactPortalProps> {  
        return (  
          <div >  
          <Myportal/>  
          </div>  
        );  
      }  
    }  

Here is the Myportal.tsx:

    import* as React from "react";  
    import usePortal from "react-cool-portal";  
    import "./mystyle.scss";  
    const  Myportal = () => {  
     // const { Portal } = usePortal({ containerId: "my-portal-root" });  
      const { Portal, show, hide } = usePortal({ defaultShow: false,containerId:"my-portal-root" });  
      const handleClickBackdrop = (e: React.MouseEvent) => {  
        const { id } = e.target as HTMLDivElement;  
        if (id === "modal") hide();  
      };  
      
      return (  
            <div className="App">  
         
          <button className="btn" onClick={show} type="button">  
            Who we are 
          </button>  
         &nbsp; &nbsp; &nbsp;
          <button className="btn" onClick={show} type="button">  
            Our value 
          </button> 
          <Portal>  
            <div  
              id="modal"  
              className="modal"  
              onClick={handleClickBackdrop}  
              tabIndex={-1}  
            >  
              <div  
                className="modal-dialog"  
                role="dialog"  
                aria-labelledby="modal-label"  
                aria-modal="true"  
              >  
                <div className="modal-header">  
                
                  <button  
                    className="modal-close"  
                    onClick={hide}  
                    type="button"  
                    aria-label="Close"  
                  >  
                    <span aria-hidden="true">×</span>  
                  </button>  
                </div>  
                <div className="modal-body">  
                 <h1> Who we are</h1>
<h3>.................................................</h3>
Our overriding purpose is to dramatically improve the reliability, efficiency........
                </div>  
              </div>  
            </div>  
          </Portal>  
        </div>  
          
      );  
    };  
    export default Myportal;  
0

2 Answers 2

1

To make your SharePoint framework web part configurable, you have to use the property pane configuration.

Make below changes in your solution to make the modal-body text configurable:

Change getPropertyPaneConfiguration() method in ReactPortalWebPart.ts file to:

protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
    return {
      pages: [
        {
          header: {
            description: strings.PropertyPaneDescription
          },
          groups: [
            {
              groupName: strings.BasicGroupName,
              groupFields: [
                PropertyPaneTextField('description', {
                  label: strings.DescriptionFieldLabel
                }),
                PropertyPaneTextField('modalBody', {
                  label: "Modal Body"
                })
              ]
            }
          ]
        }
      ]
    };
}

Change render() method in ReactPortalWebPart.ts file to:

public render(): void {
    const element: React.ReactElement<IReactPortalProps> = React.createElement(
      ReactPortal,
      {
        description: this.properties.description,
        modalBody: this.properties.modalBody
      }
    );

    ReactDom.render(element, this.domElement);
}

Add modalBody property to IReactPortalProps interface in IReactPortalProps.ts file like:

export interface IReactPortalProps {
    ... //your other properties;
    modalBody: string;
}

Change ReactPortal.tsx file to:

import * as React from 'react';  
import { IReactPortalProps } from './IReactPortalProps';  
import Myportal from "./Myportal";  

export default class ReactPortal extends React.Component<IReactPortalProps, {}> { 
  constructor(props) {
    super(props);
    this.state = {};
  }
  public render(): React.ReactElement<IReactPortalProps> {  
    //Get modalBody from component properties
    const modalBody = this.props.modalBody;
    
    return (  
      <div >  
        <Myportal modalBody={modalBody} />  
      </div>  
    );  
  }  
}

Change Myportal.tsx file to:

import * as React from "react";
import usePortal from "react-cool-portal";
import "./mystyle.scss";

const Myportal = props => {
  // const { Portal } = usePortal({ containerId: "my-portal-root" });  
  const { Portal, show, hide } = usePortal({ defaultShow: false, containerId: "my-portal-root" });
  const handleClickBackdrop = (e: React.MouseEvent) => {
    const { id } = e.target as HTMLDivElement;
    if (id === "modal") hide();
  };

  const { modalBody } = props;

  return (
    <div className="App">

      <button className="btn" onClick={show} type="button">
        Who we are
      </button>
      &nbsp; &nbsp; &nbsp;
      <button className="btn" onClick={show} type="button">
        Our value
      </button>
      <Portal>
        <div
          id="modal"
          className="modal"
          onClick={handleClickBackdrop}
          tabIndex={-1}
        >
          <div
            className="modal-dialog"
            role="dialog"
            aria-labelledby="modal-label"
            aria-modal="true"
          >
            <div className="modal-header">

              <button
                className="modal-close"
                onClick={hide}
                type="button"
                aria-label="Close"
              >
                <span aria-hidden="true">×</span>
              </button>
            </div>
            <div className="modal-body">
              <p> {modalBody} </p>
            </div>
          </div>
        </div>
      </Portal>
    </div>

  );
};
export default Myportal;

Documentation: Make your SharePoint client-side web part configurable

Also, I would recommend you to look at the code provided in below samples & see how others are implementing property pane in their web parts.

Similar web part samples:

  1. Links webpart
  2. Custom Links
12
  • 1
    thanks a lot for the very helpful reply.. but how i can allow the Description field to accept HTML code? or to render it as Rich Text editor ? is this possible? thanks
    – John John
    Nov 8, 2021 at 13:24
  • You can paste the HTML in same text box control & bind it in Myportal.tsx file like: <div className="modal-body" dangerouslySetInnerHTML={modalBody} /> Nov 8, 2021 at 13:34
  • 1
    If you want more advance controls, you can import available controls from @microsoft/sp-property-pane library OR you can use @pnp/spfx-property-controls OR build custom controls for the property pane as per your requirements. Nov 8, 2021 at 13:36
  • but i could not find any Rich Text field type inside this link @ pnp.github.io/sp-dev-fx-property-controls can u advice? thanks
    – John John
    Nov 8, 2021 at 13:39
  • 1
    Hmm, yes. Not everyone has such requirements and you will not find ready made code/example for every scenario/requirements. Nov 8, 2021 at 14:56
0

To be clear: You are looking for code that will permit the entry of arbitrary code that will display itself as a modal pop-up. Are you seeking that the parent to the pop-up be the window object or the body object? If the former, why not use the window.confirm Object? Or are you being cheeky and super-slick?

1
  • thanks for the reply.. i do not want the user to add arbitrary code... i just want to allow them to add simple text or HTML .. something similar to the approach used in this example c-sharpcorner.com/article/modal-popup-in-spfx except that i want end users to be able to add the text, instead of having it hard-coded inside the web part code.. i hope this clarify my question to you..
    – John John
    Nov 6, 2021 at 19:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.