microsoft / botframework-sdk

Bot Framework provides the most comprehensive experience for building conversation applications.
MIT License
7.46k stars 2.44k forks source link

[Question] How to bind a dialog only in main dialog? #3243

Closed fcioffi closed 6 years ago

fcioffi commented 7 years ago

Hi guys,

I'm upgrading our bot implementation with new version of botbuilder but I don't understand how bind action to a dialog without bind on subdialog also.

Example:

userBot
    .dialog('main', userBotMainDialog)
    .beginDialogAction('listConversationAction', 'listConversations', {
         matches: /^\/conversations$/i
    })
    .beginDialogAction('reportsAction', 'reports', {
        matches: /^\/reports$/i
    });

In listConversations dialog we don't want bind the reports conversation and vice versa.

What's the right way to do this?

Thanks for your help. Francesco

nwhitmont commented 7 years ago

@fcioffi For reference, what version of Bot Builder SDK are you using?

fcioffi commented 7 years ago

Hi @nwhitmont,

we are using version 3.9.0.

Thanks, Francesco

nwhitmont commented 7 years ago

Did you try:

bot.dialog('/', function (session) {
  session.send("hello from root dialog!");
});

For more information on dialogs, see: https://docs.microsoft.com/en-us/bot-framework/nodejs/bot-builder-nodejs-dialog-overview

fcioffi commented 7 years ago

???

nwhitmont commented 7 years ago

@fcioffi I don't understand your response: "???" - Can you provide more context?

Did the previous comment help you find a solution or not? If not, please provide more detail about what exactly you are trying to accomplish.

fcioffi commented 7 years ago

Hi,

Ok we not understand we :)

I have a dialog / and a subdialog A of /

I would like to bind an action on / without bind it on A also.

I hope it's more clear now.

Thanks, Francesco

nwhitmont commented 7 years ago

@fcioffi I think what you want to do is setup each dialog definition independently with an associated triggerAction(), rather than chaining them together using beginDialogAction().

Example:

userBot.dialog('main', userBotMainDialog);

userBot
    .dialog('listConversations', listConversationsDialogHander)
    .triggerAction({ matches: /^\/conversations$/i });

userBot
    .dialog('reports', reportsDialogHandler)
    .triggerAction({ matches: /^\/reports$/i });
fcioffi commented 7 years ago

Thanks,

The problem is that in conversations dialog match also reports and I don't want this.

nwhitmont commented 6 years ago

Did you try configuring each dialog with it's own trigger action? If that didn't work for you, please explain why. Feel free to post in your native language and I can have it translated.

fcioffi commented 6 years ago

Hi @nwhitmont,

thanks for your support. I'm tried the code explained. The problem is that with triggerAction method the trigger is global. So, if I match command "/conversations" and I enter into "listConversations" dialog, userBot intercept the reports commands, also when I'm in subdialog.

I would like to bind a command to a dialog and only to that dialog, not in subdialog also.

Thanks for your supports, Francesco

nwhitmont commented 6 years ago

@fcioffi Yes, the triggerAction() is global.

If you want to handle contextual action, then you can use the beginDialogAction() method, and configure the "matches" property like you would for a triggerAction(). When you use the beginDialogAction() action, it will only "match" when when the user types the trigger phrase inside that specific dialog and no others.

You can find an example in the article: Respond to user input > Handle contextual action

The following code sample shows how to attach context-sensitive help to a dialog using beginDialogAction.

// Dialog to ask for number of people in the party
bot.dialog('askForPartySize', [
    function (session) {
        builder.Prompts.text(session, "How many people are in your party?");
    },
    function (session, results) {
       session.endDialogWithResult(results);
    }
])
.beginDialogAction('partySizeHelpAction', 'partySizeHelp', { matches: /^help$/i });

// Context Help dialog for party size
bot.dialog('partySizeHelp', function(session, args, next) {
    var msg = "Party size help: Our restaurant can support party sizes up to 150 members.";
    session.endDialog(msg);
})

In this example, whenever the user enters "help", the bot will push the partySizeHelp dialog onto the stack. That dialog sends a help message to the user and then ends the dialog, returning control back to the askForPartySize dialog which reprompts the user for a party size.

It is important to note that this context-sensitive help is only executed when the user is in the askForPartySize dialog. Otherwise, the general help message from the triggerAction will execute instead. In other words, the local matches clause always takes precedence over the global matches clause. For example, if a beginDialogAction matches for help, then the matches for help in the triggerAction will not be executed.

I hope that answers your question.

fcioffi commented 6 years ago

Hi @nwhitmont, thanks for your explanoation, It's very exhaustive.

My issue with beginDialogAction is that in subdialog (in your example, partySizeHelp), eventual another beginDialogAction is also active. So if I have:

bot
    .dialog('main', mainDialog)
    .beginDialogAction('firstAction', 'firstDialog', {
         matches: /^\/first$/i
    })
    .beginDialogAction('secondAction', 'secondDialog', {
        matches: /^\/second$/i
    });

bot.dialog(firstDialog, [
  (session, args, next) => {
    builder.Prompts.text(session, "What do you do?");
    ...
  },
  (session, args, next) => {
    ...
  },
])

if an user insert a response to "What do you do?": "/second" the bot switch dialog.

I don't want this! I would like to register a beginDialogAction only for the current dialog and not for subdialog. There is a right way to do this?

Many Thanks, Francesco

nwhitmont commented 6 years ago

@fcioffi In your example code, you are binding the .beginDialogAction "firstAction" and "secondAction" to the same dialog, aka "main".

If you don't want both dialog actions to be triggered from the mail dialog, bind them to another dialog, other than "main".

fcioffi commented 6 years ago

Hi Nils,

thanks for your feedback. I would like to bind firstDialog and secondDialog to main but i don't want to bind also secondDialog to firstDialog (its child).

Thanks, Francesco