Search code examples
web-chat

Is it possible to populate the input bar in webchat with an onclick method


I'm attempting to display a list of popular questions to the user, when they click them I want them to populate the input bar and/or send the message to the bot via the directline connection.

I've attempted using the ReactDOM.getRootNode() and tracking down the input node and setting the .value attribute, but this does not populate the field. I assume there is some sort of form validation that prevents this.

Also, if I console log the input node then save it as a global variable in the console screen I can change the value that way, but then the message will not actually be able to be sent, hitting enter or the send arrow does nothing. While it may seem that the suggestedActions option would work well for this particular application, I CANNOT use it for this use case.

const [chosenOption, setChosenOption] = useState(null);

const getRootNode = (componentRoot) =>{
        let root = ReactDom.findDOMNode(componentRoot)
        let inputBar = root.lastChild.lastChild.firstChild.firstChild
        console.log('Initial Console log ',inputBar)
        setInputBar(inputBar)
    }

//in render method
{(inputBar && chosenOption) && (inputBar.value = chosenOption)}

this is the function I tried to use to find the node, the chosen option works as intended, but I cannot change the value in a usable way.

I would like the user to click on a <p> element which changes the chosenOption value and for that choice to populate the input bar and/or send a that message to the bot over directline connection.What I'm trying to accomplish


Solution

  • You can use Web Chat's store to dispatch events to set the send box (WEB_CHAT/SET_SEND_BOX) or send a message (WEB_CHAT/SEND_MESSAGE) when an item gets clicked. Take a look at the code snippet below.

    Simple HTML

    <body>
    <div class="container">
      <div class="details">
        <p>Hello World!</p>
        <p>My name is TJ</p>
        <p>I am from Denver</p>
      </div>
      <div class="wrapper">
        <div id="webchat" class="webchat" role="main"></div>
        </div>
    </div>
    <script src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
    
    <script>
        // Initialize Web Chat store
        const store = window.WebChat.createStore();
    
        // Get all paragraph elements and add on click listener
        const paragraphs = document.getElementsByTagName("p");
    
        for (const paragraph of paragraphs) {
          paragraph.addEventListener('click', ({ target: { textContent: text }}) => {
            // Dispatch set send box event
            store.dispatch({
              type: 'WEB_CHAT/SET_SEND_BOX',
              payload: {
                text
              }
            });
          });
        }
    
        (async function () {
          const res = await fetch('/directline/token', { method: 'POST' });
          const { token } = await res.json();
    
          window.WebChat.renderWebChat({
            directLine: window.WebChat.createDirectLine({ token }),
            store,
          }, document.getElementById('webchat'));
    
          document.querySelector('#webchat > *').focus();
        })().catch(err => console.error(err));
      </script>
    </body>
    

    React Version

    import React, { useState, useEffect } from 'react';
    import ReactWebChat, { createDirectLine, createStore } from 'botframework-webchat';
    
    const WebChat = props => {
      const [directLine, setDirectLine] = useState();
    
      useEffect(() => {
        const initializeDirectLine = async () => {
          const res = await fetch('http://localhost:3978/directline/token', { method: 'POST' });
          const { token } = await res.json();
          setDirectLine(createDirectLine({ token }));
        };
        initializeDirectLine();
    
      }, []);
    
      return directLine
        ? <ReactWebChat directLine={directLine} {...props} />
        : "Connecting..."
    }
    
    export default () => {
      const [store] = useState(createStore());
      const items = ["Hello World!", "My name is TJ.", "I am from Denver."]
    
      const click = ({target: { textContent: text }}) => {
        store.dispatch({
          type: 'WEB_CHAT/SET_SEND_BOX',
          payload: {
            text
          }
        });
      }
    
      return (
        <div>
          <div>
            { items.map((item, index) => <p key={index} onClick={click}>{ item }</p>) }
          </div>
          <WebChat store={store} />
        </div>
      )
    };
    

    Screenshot

    enter image description here

    For more details, take a look at the Programmatic Post as Activity Web Chat sample.

    Hope this helps!