What are HTML Panels?
TalkJS provides an easy way to add chat functionality to your website, with a nice pre-built user interface that you can customise. But sometimes, you want to add a bit of your own UI to the chat. TalkJS is rendered inside an iframe, so you can't edit the DOM directly, but we have a feature called HTML Panels that lets you load your own web page in a panel above the message field. It lets you do things like this:
The email form you see there is rendered in an HTML panel.
What are React portals?
Portals are a way for a React component to render its children in a different DOM node.
function MyComponent(props) {
return ReactDOM.createPortal(
<p>Hello</p>,
document.getElementById("someOtherElement")
);
}
You can pass anything that's renderable by React to createPortal
, including props.children
.
Combining Portals with HTML Panels
So let's say you're writing a Chatbox
component, and you want it to render a TalkJS chatbox, and you want it to contain an email form like above, but you'd also like that form to be part of your main React application.
To start, let's have a look at what the Chatbox component might look like. I'm assuming that a Session
and ConversationBuilder
object are passed as props. Read our Getting started guide to find out how to set these up.
class Chatbox extends React.Component {
constructor(props) {
super(props);
this.chatboxContainer = React.createRef();
}
componentDidMount() {
this.chatbox = this.props.session.createChatbox(this.props.conversation);
this.chatbox.mount(this.chatboxContainer.current);
}
render() {
return <div ref={this.chatboxContainer}>
</div>
}
}
Now let's add a HTML panel to hold our email form. First create an HTML file that just contains a div to hold our HTML Panel contents.
<div id="panelContent"></div>
Save it somere so that it is served from the same origin as your React application.
Next, we'll update our Chatbox component. First, we'll add a panelReady
flag in our state.
constructor {
super()
this.state = {
panelReady: false
};
this.chatboxContainer = React.createRef();
}
Then, create the HTML inside componentDidMount
:
componentDidMount() {
const chatbox = this.props.session.createChatbox(this.props.conversation);
chatbox.mount(this.chatboxContainer.current);
const panelPromise = chatbox.createHtmlPanel({
url: "path/to/file.html", // Should point to the file created above.
height: 300,
show: true
});
panelPromise.then((panel) => {
panel.DOMContentLoadedPromise.then(() => {
this.setState({
panelReady: true,
panelNode: panel.window.document.getElementById("panelContent")
})
});
});
}
And then it's time to render the portal when the panel is ready. Update the Chatbox
's render method like this
render() {
return <div ref={this.chatboxContainer}>
{this.state.panelReady && ReactDOM.createPortal(
this.state.panelNode,
<EmailForm />
)}
</div>
}
EmailForm
can be any component you like, and it works just like any other React component, even events bubble from the EmailForm to your Chatbox component.
If you run into any issues, feel free to get in touch via the popup on our website or send an email to dev@talkjs.com
Happy coding!
Top comments (0)