Reputation: 55
I wish to call one form from another form based on condition set from input of first form. When I tried this code my second form kept coming again and again from start instead of moving to next field.
public static IForm<Form1> BuildForm()
{
return new FormBuilder<Form1>()
.Message("Insert following details")
.Field(nameof(Operation))
.OnCompletion(CallOperationDialog)
.Message($"Thank you")
.Build();
}
private static async Task CallOperationDialog(IDialogContext context, Form1state)
{
if (condition1)
{
await context.Forward(Chain.From(() => FormDialog.FromForm(Form2)), ResumeAfterForm2, context.Activity.AsMessageActivity(), CancellationToken.None);
}
}
If I keep second form in same class with same type of Form1 then it keeps loading on loop.
When I had that in separate files then it says it was expecting Form2 but got Form1. How can I call one Form from another as I want to keep a guided conversation?
Upvotes: 2
Views: 553
Reputation: 16652
I reproduced your issue when set context.Wait
in the ResumeAfter
method of the first formflow dialog. This will make the second dialog ends when user sets the first filed of formflow dialog 2. Since you didn't post all code, I assume this is the problem.
Then to solve this problem, we need to wait for the result of whole formflow dialog instead of waiting for the first filed of formflow dialog, means we need to correctly use context.Wait
method, do not wait for use input if you want call the second formflow in the ResumeAfter
method of first formflow dialog.
I will call the first and second dialog both from a RootDialog
here as an example, if you want to use your first formflow dialog as a root dialog, it's a similar case.
My two FormFlow
dialog is like this:
[Serializable]
public class FFDialog1
{
public string Test { get; set; }
public string Description { get; set; }
public static IForm<FFDialog1> BuildForm()
{
return new FormBuilder<FFDialog1>()
.Message("Welcome to the first FormFlow dialog")
.Field(nameof(Test))
.Field(nameof(Description))
.Build();
}
}
public enum YesOrNo
{
Yes,
No
}
[Serializable]
public class FFDialog2
{
public YesOrNo? Confirmation;
public string Input { get; set; }
public static IForm<FFDialog2> BuildForm()
{
return new FormBuilder<FFDialog2>()
.Message("Welcome to the second FormFlow dialog")
.Field(nameof(Confirmation))
.Field(nameof(Input))
.Build();
}
}
And in RootDialog
, I call them like this:
[Serializable]
public class RootDialog : IDialog<object>
{
public Task StartAsync(IDialogContext context)
{
context.Wait(MessageReceivedAsync);
return Task.CompletedTask;
}
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
var activity = await result as Activity;
//call the first formflow dialog
var form = new FormDialog<FFDialog1>(new FFDialog1(), FFDialog1.BuildForm, FormOptions.PromptInStart, null);
context.Call(form, ResumeAfterFirstFFDialog);
}
private async Task ResumeAfterFirstFFDialog(IDialogContext context, IAwaitable<object> result)
{
var dialog = await result as FFDialog1;
//call the second formflow dialog according to the result of first one.
if (dialog.Test != null && dialog.Description != null)
{
var form = new FormDialog<FFDialog2>(new FFDialog2(), FFDialog2.BuildForm, FormOptions.PromptInStart, null);
context.Call(form, ResumeAfterSecondFFDialog);
}
}
private async Task ResumeAfterSecondFFDialog(IDialogContext context, IAwaitable<object> result)
{
//get result of formflow dialog 2.
var dialog = await result as FFDialog2;
await context.PostAsync("Work is done!");
context.Wait(MessageReceivedAsync);
}
}
Here I didn't set OnCompletion
of first formflow dialog cause the result will be submit when calling ResumeAfterFirstFFDialog
, it's the same to call second one in this method.
Upvotes: 2