简体   繁体   English

自适应卡在提交时清除输入

[英]Adaptive Card clears input on submit

From a Microsoft Teams bot I send an Adaptive Card with input fields and a Submit action. 从Microsoft Teams机器人中,我发送带有输入字段和Submit操作的Adaptive Card When the user clicks Submit I receive the data entered but the form fields are cleared. 当用户单击“ Submit我收到输入的数据,但表单字段已清除。

Why is this? 为什么是这样? What am I doing wrong? 我究竟做错了什么? This behavior is extremely annoying as I can't verify the input and ask the user to correct it. 这种行为非常令人讨厌,因为我无法验证输入并要求用户进行更正。

This happens in the desktop Teams app, Teams in a browser, Teams webchat in a web page and the Bot Emulator. 这发生在桌面上的Teams应用程序,浏览器中的Teams,网页中的Teams网络聊天和Bot仿真器中。 In the Emulator it suffices for the field to loose focus. 在“仿真器”中,该字段足以释放焦点。

In case it matters I use nodejs. 万一重要,我使用nodejs。

You're not doing anything wrong. 你没做错什么 That's just how Adaptive Cards work in Teams, perhaps as a way to signify that the data has been sent to the bot successfully. 这就是自适应卡在团队中的工作方式,也许是表示数据已成功发送到机器人的一种方式。 There may be something you can do to fix your problem though. 不过,您可能可以采取一些措施来解决您的问题。

Adaptive Card input fields have a value property that allows you to specify the field's initial value. 自适应卡输入字段具有value属性,该属性允许您指定字段的初始值。 If you send a card to the user and the input fields' value properties are populated, the fields won't be empty. 如果您将卡片发送给用户,并且输入字段的value属性已填充,则这些字段不会为空。 This means you can send such a card as an update instead of a new activity and it will look like the card has been modified in place, since Teams supports updating activities. 这意味着您可以发送卡片作为更新而不是新活动,并且看起来该卡片已被修改,因为Teams支持更新活动。 If the update uses the same card but with the values the user entered then it will look like the card remains unchanged, which would fix your problem of the values disappearing. 如果更新使用的是同一张卡,但用户输入的值相同,则卡看起来将保持不变,这将解决您的值消失的问题。

There was a question about dynamically adding input fields to Adaptive Cards, and the answer contains sample code that preserves input field values: 有一个关于将输入字段动态添加到自适应卡的问题, 答案包含保留输入字段值的示例代码:

 var inputId = `text${i}`; body.push({ type: "Input.Text", id: inputId, value: cardData[inputId] // This is where the value is preserved }); 

If you want this whole process to be made easier with prebuilt code that you can install in NuGet packages, feel free to voice your support for these ideas on GitHub: 如果您希望通过可以安装在NuGet软件包中的预构建代码使整个过程变得更容易,请随时在GitHub上表达对这些想法的支持:
Bot.Builder.Community.AdaptiveCards Bot.Builder.Community.AdaptiveCards
AdaptiveCard Prompt 自适应卡提示

While I was waiting for an answer to my question I came pretty much to the same conclusion as Kyle Delaney outlined above, you have to resend the data entered. 在等待问题的答案时,我得出的结论与上述凯尔·德莱尼(Kyle Delaney)大致相同,您必须重新发送输入的数据。

So I started to fiddle with my code and came up with this solution, not sure this is the best way. 因此,我开始摆弄我的代码,并提出了此解决方案,但不确定这是最好的方法。

As part of a waterfall step: 作为瀑布步骤的一部分:

   async W2_showCard(step) {
        const card = CardFactory.adaptiveCard(this.makeFormCard());
        return await step.prompt('formPrompt', { prompt: MessageFactory.attachment(card) });
    }

The trick is in formPrompt which also ensures the user submits the form instead of doing something else. 技巧是在formPrompt ,它还可以确保用户提交表单而不是执行其他操作。

       // Workaround to make user click Submit or cancel dialog
        this.dialogs.add(new ActivityPrompt('formPrompt', async prompt => {

            const recognizedValue = prompt.recognized.value;
            if (recognizedValue.type === ActivityTypes.Message) {
                if (recognizedValue.value) {

                    const replyToId = recognizedValue.replyToId;

                    var oldCard = prompt.options.prompt.attachments[0];

                    var validated = true;
                    oldCard.content.body.forEach((item, i, body) => {
                        if (item.type === "Input.Text" || item.type === "Input.ChoiceSet") {

                            // preserve the user input
                            const newValue = recognizedValue.value[item.id];
                            item.value = newValue;

                            // some rudimentary input validation:
                            // assumes there is a corresponding text field just 
                            // prior to the input field (input fields 
                            // can't change their color)

                            if (newValue == '') {
                                body[i - 1].color = 'Attention';
                                body[i - 1].weight = 'Bolder';
                                validated = false;
                            } else {
                                delete body[i - 1].color;
                                delete body[i - 1].weight;
                            }
                        }
                    });

                    if( validated ) {
                        // remove the submit and cancel actions (not required, debatable)
                        delete oldCard.content.actions;
                    }

                    // update the card
                    const activity = prompt.context.activity;
                    activity.attachments = [oldCard];
                    activity.id = replyToId;
                    await prompt.context.updateActivity(activity);

                    if (validated) {
                        // this is to make input available in next waterfall step
                        prompt.recognized.value = recognizedValue.value;
                        return true;
                    } else {
                        await prompt.context.sendActivity(`Please check the form. Some values are missing`);
                    }
                } else {
                    await prompt.context.sendActivity(`Please fill out form and press *"submit"* button or type *"cancel"* to stop.`);
                }

            }
            return false;

        }));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM