I have a React app and I want to replace the input bar of the Webchat with my own select element (I'm using react-select).
Here is the select element under the webchat:
return (
<div className="WebChat" >
<ReactWebChat //WebChat
className={ `${ className || '' } web-chat` }
directLine={ this.createDirectLine(token) }
store={ store }
styleSet={ styleSet } />
<Select //my select element
autoFocus="true"
className="basic-single"
classNamePrefix="select"
defaultValue={'default'}
isClearable={isClearable}
isSearchable={isSearchable}
name="Questions"
options={groupedQuestions}
closeMenuOnScroll= "true"
placeholder="Example"
/>
</div>
);
edit Thanks to @tdurnford, here is my implementation:
import React from 'react'
import { createStore } from 'botframework-webchat'
import WebChatReact from './WebChatReact'
+import Searchbox from "./ImprovedSendBox"
+import setSendBox from "botframework-webchat-core/lib/actions/setSendBox";
+import submitSendBox from "botframework-webchat-core/lib/actions/submitSendBox";
import './WebChat.css'
export default class extends React.Component {
constructor(props) {
super(props);
this.handleFetchToken = this.handleFetchToken.bind(this);
const store = createStore({}, ({ dispatch }) => next => action => {
if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
dispatch({
type: 'WEB_CHAT/SEND_EVENT',
payload: {
name: 'webchat/join',
value: { }
}
});
setTimeout(() => {
dispatch({
type: 'WEB_CHAT/SEND_MESSAGE',
payload: { text:'Démarrer' }
}
);
}, 1000);
}
+ if (action.type === 'WEB_CHAT/SET_SEND_BOX') {
+ this.setState({
+ searchValue: action.payload.text,
+ })
+ }
return next(action);
});
this.state = {
store,
token: null,
+ searchValue: "",
+ searchSelection: "",
};
}
+ handleSearchInput = (e, { action }, store) => {
+ if (
+ action === "menu-close" ||
+ action === "input-blur" ||
+ action === "set-value"
+ ) {
+ return;
+ } else {
+ this.setState({ searchValue: e });
+ }
+ store.dispatch(setSendBox(e));
+ };
+ handleSearchSelection = (selection, store) => {
+ this.setState({
+ searchSelection: selection ? selection.label : "", //Clear Button à fix
+ searchValue: selection ? selection.label : ""
+ });
+ if (selection != null){
+ store.dispatch(setSendBox(selection.label));
+ }
+ };
async handleFetchToken() {
if (!this.state.token) {
const res = await fetch('https://directline.botframework.com/v3/directline/conversations', {
method: 'POST',
headers: {
"Authorization": "secret token ;)"
}});
const { token } = await res.json();
this.setState(() => ({ token }));
}
}
render() {
const { state: {
store,
token,
+ searchValue,
+ searchSelection
} } = this;
return (
<div className="WebChat">
<WebChatReact
className="react-web-chat"
onFetchToken={ this.handleFetchToken }
store={ store }
token={ token }
/>
+ <form className="form-inline">
+ <Searchbox
+ className="select"
+ value={searchSelection}
+ onChange={e => this.handleSearchSelection(e, store)}
+ inputValue={searchValue}
+ onInputChange={(e, action) => this.handleSearchInput(e, action, store)}
+ />
+ <button
+ id="submit"
+ onClick={ event => {
+ event.preventDefault();
+ store.dispatch(submitSendBox())
+ }}
+ >
+ Submit
+ </button>
+ </form>
</div>
);
}
}
Can be found on Github
the result: If you have any questions, feel free to ask me :)
Unfortunately, there is no simple way to replace Web Chat's text input at the moment, but there is an issue open on GitHub regarding the future possibility of customizing the Send Box.
Even though there isn't a supported method to replace the send box at the moment, one option without having to fork the repo would be to hide the Send Box and render a custom one right below Web Chat. However, if you followed this approach, you would have to handle suggested actions, file attachments, and speech functionality in addition to tying Web Chat's store to the components state. You would also lose out on a lot of Web Chat's styling options.
If this is still something you'd like to pursue, here are some code snippets to get you started.
SimpleSendBox
import React from 'react';
import setSendBox from "botframework-webchat-core/lib/actions/setSendBox";
import submitSendBox from "botframework-webchat-core/lib/actions/submitSendBox";
export default ({ store, value }) => (
<div>
<form>
<input
onChange={ ({ target: { value }}) => store.dispatch(setSendBox(value)) }
placeholder="Type your message..."
value={ value }
/>
<button
onClick={ event => {
event.preventDefault();
store.dispatch(submitSendBox())
}}
>
Submit
</button>
</form>
</div>
)
App
import React, { Component } from 'react';
import WebChat from './WebChat';
import SimpleSendBox from './SimpleSendBox'
import { createStore } from 'botframework-webchat';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
store: createStore({},
() => next => action => {
if (action.type === 'WEB_CHAT/SET_SEND_BOX') {
this.setState({ value: action.payload.text })
}
return next(action);
}),
value: ""
}
}
render() {
return (
<>
<WebChat store={ this.state.store } styleOptions={{ hideSendBox: true }} />
<SimpleSendBox store={ this.state.store } value={ this.state.value }/>
</>
);
}
}
export default App;
Hope this helps!