2
votes

I am referring sample code and tried simple scenario to display card. How to continue waterfall_Dialog after card display?

I am referring sample code 05.multi-turn-prompt and 06.using-cards - (https://github.com/microsoft/BotBuilder-Samples/blob/master/samples/javascript_nodejs/05.multi-turn-prompt/dialogs/userProfileDialog.js)

      ...this.addDialog(new WaterfallDialog(WATERFALL_DIALOG, [
        this.initialData.bind(this), 
        this.displayCard.bind(this),    
        this.text.bind(this)
    ])); ...

async run(turnContext, accessor) {
   ...}

async initialData(step) {
    return await step.prompt(NAME_PROMPT, `Type anything to display card`);
} 

async displayCard(step) {
   await step.context.sendActivity({ attachments: [this.createAdaptiveCard()]});                
}

async text(step) {
    console.log("step.res"+step.context.activity.text);
    await step.context.sendActivity("Thank you for selecting an option");

}

async displayCard(step) {
   await step.context.sendActivity({ attachments: [this.createAdaptiveCard()]});                
  return await this.text(step);
} 

To display card and continue waterfall Dialog.

After display of card it should continue the flow and display "Thank you for selecting an option",

  1. But it is going to Begin_Dialog and asking for " Type anything to display card"

  2. If I try other approach by call the next dialog. I get "Oops. Something went wrong!" "[onTurnError]: TypeError: Cannot read property 'status' of undefined"

2

2 Answers

0
votes

To advance to the next dialog step you need to call NextAsync following the step that includes the card.

For example,

private async Task<DialogTurnResult> StartSelectionStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
    // Set the user's age to what they entered in response to the age prompt.
    var userProfile = (UserProfile)stepContext.Values[UserInfo];
    userProfile.Age = (int)stepContext.Result;

    if (userProfile.Age < 25)
    {
        // If they are too young, skip the review selection dialog, and pass an empty list to the next step.
        await stepContext.Context.SendActivityAsync(
            MessageFactory.Text("You must be 25 or older to participate."),
            cancellationToken);
        return await stepContext.NextAsync(new List<string>(), cancellationToken);
    }
    else
    {
        // Otherwise, start the review selection dialog.
        return await stepContext.BeginDialogAsync(nameof(ReviewSelectionDialog), null, cancellationToken);
    }
}

In the above snippet, if the user is not of the correct age a message is displayed saying as much. return await stepContext.NextAsync() is called which advances the dialog to the next step. If the user is of age, then a new dialog is begun ("ReviewSelectionDialog"). The snippet comes from the docs on "Create advanced conversation flow using branches and loops", located here, that you can reference.

Hope of help!

0
votes

Here, I attach the code of multiple dialog sets. you just need to register dialog in dialog set before begin or replace dialogs.

this.flowBuilderDialog and this.faqDialog is the dialog objects and DialogsNameList.FLOW_BUILDER_DIALOG and DialogsNameList.FAQ_DIALOG are name of the dialogs.

class GreetingDialog extends ComponentDialog {
constructor(dialogId, userInfoPropertyAccessor, flowNextQuestionAccessor, flowBuilderConversationAccessor, flowBuilderDialog, faqDialog) {
    super(dialogId);

    if (!userInfoPropertyAccessor) throw new Error(`[MainDialog]: Missing parameter \'userInfoPropertyAccessor\' is required`);
    if (!flowBuilderDialog) throw new Error(`[MainDialog]: Missing parameter \'flowBuilderDialog\' is required`);
    if (!faqDialog) throw new Error(`[MainDialog]: Missing parameter \'faqDialog\' is required`);
    // Define the greeting dialog and its related components.

    let greetingChoicePrompt = new ChoicePrompt(GREETING_CHOICE_PROMPT);
    greetingChoicePrompt.style = ListStyle.heroCard;

    this.addDialog(greetingChoicePrompt)
        .addDialog(new WaterfallDialog(GREETING_WATERFALL_DIALOG, [
            this.introStep.bind(this),
            this.actStep.bind(this),
            this.finalStep.bind(this)
        ]));

    this.flowBuilderDialog = flowBuilderDialog;
    this.faqDialog = faqDialog;

    this.initialDialogId = GREETING_WATERFALL_DIALOG;
    this.flowNextQuestionAccessor = flowNextQuestionAccessor;
    this.flowBuilderConversationAccessor = flowBuilderConversationAccessor;
}

/**
 * The run method handles the incoming activity (in the form of a TurnContext) and passes it through the dialog system.
 * If no dialog is active, it will start the default dialog.
 * @param {*} turnContext
 * @param {*} accessor
 */

async run(turnContext, accessor) {
    const dialogSet = new DialogSet(accessor);
    dialogSet.add(this);
    dialogSet.add(this.flowBuilderDialog);
    dialogSet.add(this.faqDialog);

    const dialogContext = await dialogSet.createContext(turnContext);

    const results = await dialogContext.continueDialog();
    if (results.status === DialogTurnStatus.empty) {
        await dialogContext.beginDialog(this.id);
    }
}


async introStep(stepContext) {
    return await stepContext.prompt(GREETING_CHOICE_PROMPT, {
        prompt: 'How can I help you today?',
        choices: ChoiceFactory.toChoices(['Flow Builder', 'FAQ'])
    });
}

async actStep(stepContext) {
    console.log("Step: Result", stepContext.result);

    switch (stepContext.result.value) {
        case 'Flow Builder':
            await this.flowNextQuestionAccessor.set(stepContext.context, 0);
            await this.flowBuilderConversationAccessor.set(stepContext.context, '');
            return await stepContext.replaceDialog(DialogsNameList.FLOW_BUILDER_DIALOG);
        case 'FAQ':
            return await stepContext.replaceDialog(DialogsNameList.FAQ_DIALOG);
    }
}

async finalStep(stepContext) {
    return await stepContext.replaceDialog(this.initialDialogId, {restartMsg: 'What else can I do for you?'});
}

}