【问题标题】:How can i clear the chat input-box after sending the message(from suggestion) in botframework webchat?在 botframework 网络聊天中发送消息(来自建议)后,如何清除聊天输入框?
【发布时间】:2023-03-22 17:51:02
【问题描述】:

我正在使用 react js 和 botframework 网络聊天开发一个机器人应用程序。问题是我想在发送消息后清除文本输入框(从那里发送消息) - 这是从建议中选择的。建议列表(或自动完成组件)是自定义编码的。我的意思是,如果我输入“hr”,建议列表弹出窗口就会出现,如果我点击建议中的一个选项,比如“hr 门户”,它将被发送,但我写的内容,即“hr”仍然存在在输入字段中,我想清除它。请注意,如果我输入一些东西并发送它的工作正常。问题只是当我输入一些东西并从建议中选择一些东西时。其他一切都很好。我怎样才能清除它。任何帮助将不胜感激。

请看下图了解更多。

这是我的代码;

import React from 'react';
import { DirectLine, ConnectionStatus } from 'botframework-directlinejs';
import ReactWebChat from 'botframework-webchat';
import './ChatComponent.css';
var val;
var apiParameters = [];
var currentFocus = -1;
export default class extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            token: '',
            conversationId: '',
            directLine: {},
            view: false,
            feedBack: null,
            value: '',
            popupContent: '',
            storeValue: '',
            suggestions: [],
            suggestionCallback: '',
            suggestionTypedText: "",
            typingChecking: "false",
        };
        this.handleTokenGeneration = this.handleTokenGeneration.bind(this);
        this.handleChange = this.handleChange.bind(this);
        this.handleSaveFeedback = this.handleSaveFeedback.bind(this);
        this.handleSuggestion = this.handleSuggestion.bind(this);
        this.handleClose = this.handleClose.bind(this);
        this.handleSuggestionClick = this.handleSuggestionClick.bind(this);
        this.handleKeyDown = this.handleKeyDown.bind(this);
        this.moveHighlight = this.moveHighlight.bind(this);
        this.getSuggestionHtml = this.getSuggestionHtml.bind(this);
    }
    getSuggestionHtml(suggestion) {
        const lowerCaseSuggestion = suggestion.toLowerCase();
        return {
            __html: lowerCaseSuggestion.includes(this.state.suggestionTypedText) ? lowerCaseSuggestion
                .replace(this.state.suggestionTypedText, `<b>${this.state.suggestionTypedText}</b>`) : lowerCaseSuggestion
        };
    }
    handleTokenGeneration = async () => {
        console.log("11111");
        const response = await fetch(`api/TokenGenerationService/GetToken`);
        const data = await response.json();
        this.setState({
            token: data.categoryObject.token, conversationId:
                data.categoryObject.conversationId
        });
        this.state.directLine = new DirectLine({ token: this.state.token });
        this.setState({ view: true });
        this.setState({ typingChecking: "true" });
        console.log("conversationId");
    };
    async handleSuggestion(val, store) {
        if (val === "") {
            this.setState({
                suggestions: []
            });
        }
        else {
            apiParameters = [];
            var valuess = null;
            const response = await fetch(`api/TokenGenerationService/GetAzureSearch?myparam1=${val}`);
            const data = await response.json();
            var values = ["Hello", "yes", "no", "exit", "Welcome", "Thank You", "Approve", "Apply leave", "Reject", "Absence Balance", "Leave Balance", "Upcoming Holidays", "Apply Comp-Off", "Approve Leave", "Raise Incident Tickets", "Project Allocation Info", "Reporting Manager Change", "Reporting Manager Approval", "Approve Isolve Tickets", "My Manager", "My Account Manager", "Generate Salary Certificate", "Isolve Ticket Status", "Internal Job Posting", "My Designation", "My Joining Date", "RM Approval", "RM Change", "Resource Allocation", "ESettlement Approval", "SO Approval", "Cash advance Approval", "Purchase Request Approval", "Referral status", "HR Ticket", "Platinum Support"];
            valuess = values.filter(s =>
                s.toLocaleLowerCase().startsWith(val.toLowerCase())
            );
            valuess = valuess.concat(data.az_search);
            this.setState({
                suggestions: valuess,
                suggestionCallback: store,
                suggestionTypedText: val.toLowerCase()
            });
            // alert(data.az_search);
            var totCount = data.az_search;
            console.log("kkkkkk" + totCount);
        }
    }
    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,
            });
        }
    }
    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) {
        // console.log("lokkkkkkkkkkkk")
        if (this.keyDownHandlers[event.key])
            this.keyDownHandlers[event.key].call(this, event)
    }
    async handleSuggestionClick(event) {
        await this.applySuggestion(event.currentTarget.textContent);
    }
    async applySuggestion(newValue) {
        //newValue = null;
        await this.setState({ typingChecking: "false", suggestions: [], highlightedIndex: 0 });
        this.state.suggestionCallback.dispatch({
            type: 'WEB_CHAT/SEND_MESSAGE',
            payload: {
                text: newValue
            }
        });
        await this.setState({ typingChecking: "true" });
    }
    getSuggestionCss(index) {
        var HIGHLIGHTED_CSS = "HIGHLIGHTED_CSS";
        var SUGGESTION_CSS = "SUGGESTION_CSS";
        return index === this.state.highlightedIndex ? HIGHLIGHTED_CSS : SUGGESTION_CSS;
    }
    handleClose(elmnt) {
        var x = document.getElementsByClassName("autocomplete-items");
        for (var i = 0; i < x.length; i++) {
            if (elmnt !== x[i]) {
                x[i].parentNode.removeChild(x[i]);
            }
        }
    }
    async componentDidMount() {
        try {
            await this.handleTokenGeneration();
            const store =
                window.WebChat.createStore(
                    {},
                    ({ getState }) => next => action => {
                        this.state.directLine.connectionStatus$
                            .subscribe(connectionStatus => {
                                if (connectionStatus === ConnectionStatus.ExpiredToken) {
                                    console.log("expired");
                                }
                                if (action.type === 'WEB_CHAT/SET_SEND_BOX') {
                                    const val = action.payload.text;
                                    if (this.state.typingChecking === "true") {
                                        this.setState({
                                            highlightedIndex: -1,
                                        });
                                        console.log(this.state.typingChecking);
                                        this.handleSuggestion(val, store);
                                    }
                                }
                                if (action.type === 'DIRECT_LINE/DISCONNECT_FULFILLED') {
                                    console.log("final" + connectionStatus);
                                    console.log("finalexpired" + ConnectionStatus.ExpiredToken);
                                    console.log("final");
                                    this.handleTokenGeneration();
                                }
                            });
                        return next(action)
                    }
                );
            this.setState({ storeValue: store });
        } catch (error) {
            console.log("error in fetching token");
            console.log(error);
        }
        this.state.directLine.activity$
            .filter(activity => activity.type === 'message')
            .subscribe(function (activity) {
                //console.log("oooooooooooooooooooooo");
            }
                // message => console.log("received message ", message.text)
            );
    }
    handleSaveFeedback(ans) {
        // console.log(this.state.conversationId);
        //  console.log(this.state.feedBack);
        var userID = "C94570";
        var feedbackmsg = this.state.value;
        var feedbacktype = this.state.feedBack;
        var convId = this.state.conversationId;
        fetch('api/Feedback/SaveFeedback',
            {
                method: "POST",
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ Uid: userID, FeedbackMessage: feedbackmsg, Convid: convId, FeedbackType: feedbacktype })
            }).
            then(response => response.text())
            .then(data => {
                console.log(data.getResult);
            });
        this.setState({ value: '' });
    }
    feedback(ans) {
        this.setState({ feedBack: ans });
        if (ans === "Send") {
            this.handleSaveFeedback(ans);
        }
        else if (ans === "Yes") {
            this.setState({ popupContent: "How was your experience?" });
            // console.log(this.state.value)
        }
        else if (ans === "No") {
            this.setState({ popupContent: "What went wrong?" });
            // console.log(this.state.value)
        }
    }
    handleChange = (event) => {
        this.setState({ value: event.target.value });
    }
    styleOptions = {
        bubbleBackground: 'rgba(0, 0, 255, .1)',
        bubbleFromUserBackground: 'rgba(0, 255, 0, .1)',
        botAvatarInitials: 'DIA',
        userAvatarInitials: 'ME'
    }
    render() {
        if (!this.state.view) {
            return
            <div />
        } else {
            const filteredSuggestions = this.state.suggestions.filter(
                suggestion =>
                    suggestion.toLowerCase().indexOf(this.state.suggestionTypedText.toLowerCase())
                    > -1
            );
            //   console.log(this.state.view);
            return (
                <div className="react-container webchat" >
                    <div onKeyDown={this.handleKeyDown.bind(this)}>
                        <div >
                            <ReactWebChat styleOptions={this.styleOptions} directLine={this.state.directLine} webSocket={true} userID='C94570' username='Thomas' store={this.state.storeValue} sendTypingIndicator={true} />
                        </div>
                    </div>
                    <div className="SuggestionParent" id="Suggestion1">
                        {this.state.suggestions.map((suggestion, index) => (
                            <div className={this.getSuggestionCss(index)} key={index} onClick={this.handleSuggestionClick} >
                                {suggestion
                                    .toLowerCase()
                                    .startsWith(this.state.suggestionTypedText) ? (
                                        <div>
                                            <b>{this.state.suggestionTypedText}</b>
                                            {suggestion
                                                .toLowerCase()
                                                .replace(this.state.suggestionTypedText, "")}
                                        </div>
                                    ) : (
                                        <div dangerouslySetInnerHTML={this.getSuggestionHtml(suggestion)} />
                                    )}
                            </div>
                        ))}
                    </div>
                    <footer className="chat-footer" >
                        <div className="foot-footer">
                            Was I helpful ?
         <span className="feedback" onClick={() => this.feedback("Yes")} >Yes</span><span>|</span><span className="feedback" onClick={() => this.feedback("No")}>No</span>
                            {
                                this.state.feedBack === "Yes" || this.state.feedBack === "No" ?
                                    (
                                        <div className="dialog" id="myform">
                                            <div id="textfeedback">
                                                <span id="closeFeedback" onClick={() => this.feedback("Close")}>X</span>
                                                <p>{this.state.popupContent}</p>
                                                <input type="text" id="feedbacktxtbox" required name="textfeedback" placeholder="Pleasure to hear from u!"
                                                    onChange={this.handleChange}
                                                    value={this.state.value} />
                                                <button type="button" id="btnfeedback" onClick={() => this.feedback("Send")}>send</button>
                                            </div>
                                        </div>
                                    ) : null
                            }
                        </div>
                    </footer>
                </div>
            );
        }
    }
}

【问题讨论】:

  • Puhh 抱歉,Thomas,别想我能帮上忙,不妨试试这个:Chat.post($('input[name=\'content\']').val()); $('.input').val("") 或者用 jquery 清除?
  • @TimCadenbach 感谢您的回复。其实问题出在建议上。我想知道是否有任何反应或机器人动作可以做到这一点。
  • @ThomasMartin - 你能修复你的代码吗?我粘贴到 Visual Studio 并尝试对其进行格式化,发现缺少大括号等。确保代码运行并且格式正确(因此不要连续有多个空行等)
  • @KyleDelaney 嗨,凯尔,感谢您的回复。好的,我已经格式化并更新了代码。请检查
  • @KyleDelaney 问题已更新。

标签: javascript reactjs botframework direct-line-botframework web-chat


【解决方案1】:

聊天输入框在网络聊天中称为发送框。清除发送框只是将发送框设置为空字符串。当您正常单击发送按钮时,此操作会自动完成。在submit send box saga可以看到,提交发送框意味着执行两个动作:发送消息和设置发送框。

if (sendBoxValue) {
  yield put(sendMessage(sendBoxValue.trim(), method, { channelData }));
  yield put(setSendBox(''));
}

这意味着如果您使用SUBMIT_SEND_BOX 操作,那么发送框将被自动清除。当然,如果您希望它与您的自动完成组件一起使用,那么您需要在提交之前使用自动完成文本设置发送框。您的另一个选择是在发送消息后仅使用带有空字符串的 SET_SEND_BOX 操作。

【讨论】:

  • 所以我可以使用SUBMIT_SEND_BOX 代替SEND_MESSAGE 吗? “您需要在提交之前使用自动完成的文本设置发送框”是什么意思。请注意,我从SET_SEND_BOX 更改为SEND_MESSAGE 操作,因为当通过输入或鼠标单击选择选项时,我无法从建议弹出窗口发送消息。使用SEND_MESSAGE 工作正常。
  • 你不可能只用一个动作就能做你想做的事。您可以使用 SET_SEND_BOX + SUBMIT_SEND_BOX,也可以使用 SEND_MESSAGE + SET_SEND_BOX。
  • 嘿,凯尔,我刚刚通过进行以下更改来清除它,PFA,@ 987654322@ 现在有一个问题,当我输入某些内容并尝试通过以下方式将其删除时,弹出的建议不会关闭按退格键。例如,如果我输入 hr 并按退格键,则弹出的 h 建议将保留在那里。我该如何解决?
  • 您是说这是您之前没有观察到的行为,并且只是由清除发送框的新代码引入的?无论如何,根据您提供给我的信息,我认为我不可能知道如何帮助您。我觉得你还是个初学者,所以我的建议是参加一些关于 React、JavaScript、UI 和编程基础的课程。如果您不这样做,那么您将不断陷入困境并遇到无法靠自己解决的问题。一旦你给它一个很好的尝试,那么你应该问一个包含所有细节的新问题。
  • 实际上问题在于建议弹出窗口(自动完成组件)即使使用退格键清除键入的文本也不会关闭。最后一个删除单词的建议列表未关闭。这就是问题所在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-12
  • 2021-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多