Skip to content

Fill Form Helper

MohammadReza edited this page Aug 20, 2021 · 2 revisions

Simply fill a form with flamingo

Flamingo has a feature that helps you ask an entire from data from user as easy as possible.

Create your model

Assume you have a form like below:

public enum Gender
{
    None = 0,

    Male = 1,

    Female = 2,
}

public class UserDataForm
{
    public string FirstName { get; set; }

    public string LastName { get; set; }

    public int Code { get; set; }

    public Gender Gender { get; set; } = Gender.None;

    public string FullName => $"{FirstName} {LastName} ({Code}) ({Gender})";
}

Mark properties

Now if are interested to fill some of properties using form filler, you should mark them for Flamingo, using an attribute named [FlamingoFormProperty]

add references to following namespace

using Flamingo.Fishes.Awaitables.FillFormHelper;

Mark properties that should be asked from user.

public class UserDataForm
{
    [FlamingoFormProperty]
    public string FirstName { get; set; }

    [FlamingoFormProperty]
    public string LastName { get; set; }

    [FlamingoFormProperty]
    public int Code { get; set; }

    [FlamingoFormProperty]
    public Gender Gender { get; set; } = Gender.None;

    public string FullName => $"{FirstName} {LastName} ({Code}) ({Gender})";
}

In this case we do need FullName to be asked!

You can also mark a property as optional

All properties that marked by [FlamingoFormProperty] are Required by default.

[FlamingoFormProperty(Required = false)]
public Gender Gender { get; set; } = Gender.None;

Add data checks

You add checks for properties into your model!

add references to following namespace

using Flamingo.Fishes.Awaitables.FillFormHelper.FromDataChecks;

Add everything you like!

public class UserDataForm
{
    [FlamingoFormProperty]
    [StringLength(10, FailureMessage = "10 char at most")]
    [StringRegex(@"^[a-zA-Z]+$", FailureMessage = "only letters")]
    public string FirstName { get; set; }

    [FlamingoFormProperty]
    [StringLength(10)]
    [StringRegex(@"^[a-zA-Z]+$", FailureMessage = "only letters")]
    public string LastName { get; set; }

    [FlamingoFormProperty]
    public int Code { get; set; }

    [FlamingoFormProperty(Required = false)]
    public Gender Gender { get; set; } = Gender.None;

    public string FullName => $"{FirstName} {LastName} ({Code}) ({Gender})";
}

There are not too much ready to use data checks but you can create you own! ( as always in flamingo )

Create custom data check

You can take a look at an example of creating a data check for form properties.

StringMaxLength

Use filler into your handler

    [CommandFilter("form")]
    [ChatTypeFilter(FlamingoChatType.Private)]
    public class MyAdvMessageInComing : AdvInComingMessage
    {
        protected override async Task GetEatenWrapper(Message inComing)
        {
            // Creates a form filler instance for `UserDataForm` class
            // 'StatusChanged' is a callback function that is called when 
            // status changed in asking process (eg new answer, validation failure, ...)
            // this functions provides enough information about filler and can cancel
            // processing there is you suppose to using 'filler.Terminate()'
            var filler = Flamingo.CreateFormFiller<UserDataForm>(StatusChanged);

            // Asks user for marked properties of `UserDataForm`
            // And allows user to fail for 1 time ( Type check failure or value checks )
            await filler.Ask(
                Cdmt.SenderId,
                triesOnFailure: 1,
                timeOut: 10,
                cancellInputPattern: new Regex("^/cancel"));

            if (filler.Succeeded)
                // filler.Instance is an instance of `UserDataForm` which is filled!
                await ReplyText(filler.Instance.FullName);
            else if (filler.Canceled)
                await ReplyText("See you.");
            else if (filler.TimedOut)
                await ReplyText("Answer faster next time.");
            else if (filler.Terminated)
                await ReplyText("Operation terminated.");
            else
                await ReplyText("Something wrong try again.");
        }

        // if this function returns false then no message will send to user.
        private bool StatusChanged(
            FillFormRequest<UserDataForm> form,
            FlamingoFormStatus status,
            IFlamingoFormData data)
        {
            if (status == FlamingoFormStatus.TimedOut)
            {
                // This means: don't send any further message for this question
                return false;
            }
            else if (status == FlamingoFormStatus.RecoverableTimedOut)
            {
                form.Flamingo.BotClient.SendTextMessageAsync(
                    form.UserId, $"You missed {data.Name}. but no worries it's optional!");

                return false;
            }
            else if (status == FlamingoFormStatus.ValidatingFailed)
            {
                form.Flamingo.BotClient.SendTextMessageAsync(
                    form.UserId, $"No mistakes allowed!");
                form.Terminate();

                return false;
            }

            return true;
        }
    }

Flamingo Framework written in pure c#, install from Nuget

Clone this wiki locally