SOLVED

SPFX web part to add Text and show it inside a Popup when clicking on a button

Valued Contributor

I am trying to achieve this using SPFX web part:-

  1. The web part will render a Button and has a text field inside its settings.

  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 @ https://www.c-sharpcorner.com/article/modal-popup-in-spfx/ which almost achieve 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?

Thanks

 

 

 

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;

 

3 Replies
best response confirmed by Beau Cameron (MVP)
Solution

@john john 

You need to pass the text to display variable (which looks like the description property in the property panel) into the MyPortal React element.  It is already being passed into the ReactPortal React component as part of the IReactPortalProps object, so you just need to pass that through to MyPortal as an attribute.

 

First, change line 4 in MyPortal.tsx to 

 

const Myportal = (textToDisplay: string) => {

 

 

To use the parameter, place it in the return object. It looks like you want to replace line 49 in MyPortal.tsx with

 

{textToDisplay}

 

 

To pass the description property into MyPortal, replace line 8 in ReactPortal.tsx with 

 

<Myportal textToDisplay={props.description}/>

 

 

I hope this help show how to pass properties into React function components. If this helps, please consider marking this as the approved solution.

 

Good luck,

Don Kirkham

@Don Kirkhamok thanks a lot for the help.. but how i can show the Description field as Multi-line of text that accept HTML code? or if i can render it as Rich Text Editor? as i need the text inside the Popup to be rich text rather than been just a text-only.. can i achieve this?

This can be done, but it is well beyond the scope of your original question.

I recommend that you look at the samples available in Microsoft PnP. There is a Rich Text control that could display your text, but editing it in a popup is not easy. There is not a Rich Text Property Pane control, but it is possible to create a custom control with a popup that has the Rich Text control in it, for editing.

PnP is a great source for all kinds of samples and code to shortcut the developer experience, so I recommend going through as much of it as you can. (Including a lot of instructional videos.)

Best of luck,
Don