Ad

How To Take A Key Up/down In Web Chat Using React

- 1 answer

I am currently doing bot-framework web chat application using react js.I want to know how can i take a key up/down. As i want to select or highlight through suggestion list using arrow keys. My code which i used for the react component is attached below, PFA,

async handleSuggestionClick(val) {
  const newValue = val.currentTarget.textContent;

  await this.setState({ typingChecking: "false" },
    () => { console.log(this.state.typingChecking) });

  await this.setState({ suggestions: [] },
    () => { console.log(this.state.suggestions) });


  this.state.suggestionCallback.dispatch({
    type: 'WEB_CHAT/SET_SEND_BOX',
    payload: {
        text: newValue,
    }
  });
  await this.setState({ typingChecking: "true" },
    () => { console.log(this.state.typingChecking) });
}

<div className="react-container webchat" >
    <ReactWebChat directLine={this.state.directLine} 
      webSocket={true}  
      store={this.state.storeValue} 
      sendTypingIndicator={true} />
    <div className="SuggestionParent" id="Suggestion1">
      {this.state.suggestions.map(suggestion => (
        <div className="Suggestion" 
          onClick={this.handleSuggestionClick} 
          onKeyDown={this.handleKeyDown}>
          {suggestion
            .toLowerCase()        
            .startsWith(this.state.suggestionTypedText) ? 
               (<div>
                  <b> 
                    {this.state.suggestionTypedText}
                  </b>
                  {suggestion
                    .toLowerCase()
                    .replace(this.state.suggestionTypedText, "")}
                </div>) : 
                (<div>{suggestion}</div>
              )
           }
        </div>
      ))
     }
</div>
Ad

Answer

From the answer to your duplicate issue: Issues with suggestion list in botframework Webchat React

Keyboard events are generally handled in React using the onKeyDown property. I've placed it on an element that contains both Web Chat and your suggestions parent:

<div className={ROOT_CSS} onKeyDown={this.handleKeyDown.bind(this)}>
  <div className={WEB_CHAT_CSS + ''}>
    <ReactWebChat

That will handle all key presses, so you'll need a way to route to the function for the correct key. You could use a switch statement but the source code for [react-autocomplete][3] uses a lookup object and I think that's smart.

keyDownHandlers = {
  ArrowDown(event) {
    this.moveHighlight(event, 1);
  },
  ArrowUp(event) {
    this.moveHighlight(event, -1);
  },
  Enter(event) {
    const {suggestions} = this.state;
    if (!suggestions.length) {
      // menu is closed so there is no selection to accept -> do nothing
      return
    }
    event.preventDefault()
    this.applySuggestion(suggestions[this.state.highlightedIndex]);
  },
}

handleKeyDown(event) {
  if (this.keyDownHandlers[event.key])
  this.keyDownHandlers[event.key].call(this, event)
}

I've centralized the functionality for the up and down arrows into one function: moveHighlight. You will need to define a new property in your state to keep track of which suggestion has been selected by the keyboard. I'm keeping the name highlightedIndex from react-autocomplete.

moveHighlight(event, direction) {
  event.preventDefault();
  const { highlightedIndex, suggestions } = this.state;
  if (!suggestions.length) return;
  let newIndex = (highlightedIndex + direction + suggestions.length) % suggestions.length;
  if (newIndex !== highlightedIndex) {
    this.setState({
      highlightedIndex: newIndex,
    });
  }
}
Ad
source: stackoverflow.com
Ad