Auto-completion : How to replace the input field of the Webchat with your own react-select element

爱⌒轻易说出口 提交于 2020-01-16 18:18:16

问题


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:

WebChat.js

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>
    );
  }
}

ImprovedSendBox.js

Can be found on Github

the result:

If you have any questions, feel free to ask me :)

回答1:


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!



来源:https://stackoverflow.com/questions/56234790/auto-completion-how-to-replace-the-input-field-of-the-webchat-with-your-own-re

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!