Create a wizard page

Completed

A wizard page guides a user through the installation process. The wizard page is called from within Assisted Setup. To build a wizard page, you need to set the PageType property to NavigatePage. The purpose of a wizard is to enable a user to configure settings and store those settings only when the user selects the Finish button. Because Business Central automatically stores all modifications from the moment you leave an input field, you need to set the SourceTableTemporary property to true. This setting ensures that modifications are only stored in memory and that, when the user select the Finish button, you can copy the modifications from memory to the database.

The following example shows a wizard being created to configure the company information.

page 50103 "Company Setup Wizard"
{
    Caption = 'Company Setup';
    PageType = NavigatePage;
    SourceTable = "Company Information";
    SourceTableTemporary = true;
    ...
}

Layout wizard steps

A wizard contains a number of steps; therefore, you need to create a group for each step and a global variable for each group. This variable is linked to the Visible property of the group so that you can hide or show a group (or step) of the wizard.

These variables are changed in code, depending on which step of the wizard that the user is working on. For each step on the wizard page, you also define a value in an option variable. This variable is used to track which step is active. In the following example, the wizard contains three steps.

layout
{
    area(content)
    {
        group(StandardBanner)
        {
            Visible = TopBannerVisible and not FinishActionEnabled;
            ...
        }
        group(FinishedBanner)
        {
            Visible = TopBannerVisible and FinishActionEnabled;
            ...
        }
        group(Step1)
        {
            Visible = Step1Visible;
            ...
        }
        group(Step2)
        {
            Visible = Step2Visible;
            ...
        }
        group(Step3)
        {
            Visible = Step3Visible;
            ...
        }
    }
}

var
    TopBannerVisible: Boolean;
    BackActionEnabled: Boolean;
    FinishActionEnabled: Boolean;
    NextActionEnabled: Boolean;
    Step1Visible: Boolean;
    Step2Visible: Boolean;
    Step3Visible: Boolean;
    Step: Option Start,Step2,Finish;

Within the groups, you can specify text through the InstructionalText property, or you can put fields on the page so a user can specify the necessary settings.

group(Step1)
{
    Visible = Step1Visible;
    group("Welcome to Company Setup")
    {
        Caption = 'Welcome to Company Setup';
        InstructionalText = 'To prepare Dynamics 365 Business Central ...';
    }
    group("Let's go!")
    {
        Caption = 'Let's go!';
        InstructionalText = 'Choose Next to specify basic company info.';
    }
}

The following screenshot shows the results of this code.

Screenshot of the code result Company Setup Step.

To add fields to the page, you can use the tfield snippet, similar to what you would do on any other card or list page.

group(Step2)
{
    Caption = 'Specify your company's address information and logo.';
    InstructionalText = 'This is used in invoices and other documents...';
    Visible = Step2Visible;

    field(Name; Name)
    {
        ApplicationArea = Basic, Suite;
        Caption = 'Company Name';
        NotBlank = true;
        ShowMandatory = true;
    }
    field(Address; Address)
    {
        ApplicationArea = Basic, Suite;
    }
    field("Address 2"; "Address 2")
    {
        ApplicationArea = Basic, Suite;
        Visible = false;
    }
    field(City; City)
    {
        ApplicationArea = Basic, Suite;
    }
    field("Post Code"; "Post Code")
    {
        ApplicationArea = Basic, Suite;
    }
    field("Country/Region Code"; "Country/Region Code")
    {
        ApplicationArea = Basic, Suite;
        TableRelation = "Country/Region".Code;
    }
    field("VAT Registration No."; "VAT Registration No.")
    {
        ApplicationArea = Basic, Suite;
        Visible = false;
    }
}

The following screenshot shows the result of this code.

Screenshot of the Company Setup Page code result.

Wizard actions

To go to the next step or the previous step in a wizard, you need to create page actions in the Processing area and set the InFooterBar property of each action to true. Selecting these buttons will evaluate which group should be visible. Similar to the Visible property on the groups, you can use the Enabled property to enable or disable buttons during the wizard process. These buttons are also linked to global variables that are controlled in code.

actions
{
    area(processing)
    {
        action(ActionBack)
        {
            ApplicationArea = All;
            Caption = 'Back';
            Enabled = BackActionEnabled;
            Image = PreviousRecord;
            InFooterBar = true;
            trigger OnAction();
            begin
                NextStep(true);
            end;
        }
        action(ActionNext)
        {
            ApplicationArea = All;
            Caption = 'Next';
            Enabled = NextActionEnabled;
            Image = NextRecord;
            InFooterBar = true;
            trigger OnAction();
            begin
                NextStep(false);
            end;
        }
        action(ActionFinish)
        {
            ApplicationArea = All;
            Caption = 'Finish';
            Enabled = FinishActionEnabled;
            Image = Approve;
            InFooterBar = true;
            trigger OnAction();
            begin
                FinishAction();
            end;
        }
    }
}

In the previous example and following code sample, the button will implement a NextStep function when the button is selected. Depending on which button is selected, the NextStep function will go forward or backward in the wizard.

local procedure NextStep(Backwards: Boolean);
begin
    if Backwards then
        Step := Step - 1
    else
        Step := Step + 1;

    EnableControls();
end;

local procedure EnableControls();
begin
    ResetControls();

    case Step of
        Step::Start:
            ShowStep1();
        Step::Step2:
            ShowStep2();
        Step::Finish:
            ShowStep3();
    end;
end;

local procedure ShowStep1();
begin
    Step1Visible := true;

    FinishActionEnabled := false;
    BackActionEnabled := false;
end;

local procedure ShowStep2();
begin
    Step2Visible := true;
end;

local procedure ShowStep3();
begin
    Step3Visible := true;

    NextActionEnabled := false;
    FinishActionEnabled := true;
end;

local procedure ResetControls();
begin
    FinishActionEnabled := false;
    BackActionEnabled := true;
    NextActionEnabled := true;

    Step1Visible := false;
    Step2Visible := false;
    Step3Visible := false;
end;

To end the wizard, a user needs to select the Finish button. This action will copy the values from the temporary table to the database. Therefore, you can use the TransferFields function.

local procedure FinishAction();
begin
    StoreRecordVar();
    CurrPage.Close();
end;

local procedure StoreRecordVar();
var
    RecordVar: Record "Company Information";
begin
    if not RecordVar.Get() then begin
        RecordVar.Init();
        RecordVar.Insert();
    end;

    RecordVar.TransferFields(Rec, false);
    RecordVar.Modify(true);
end;

Wizard banners

In Business Central, wizard pages typically show a banner at the top of the page. You can reuse the built-in banners to provide the user with a uniform experience.

Screenshot of the Standard Banner for company setup.

Screenshot of the Finished Banner for company setup.

The banner is displayed in a group that you need to define in the Content area. Depending on the current step in the wizard, either the Standard Banner or the Finished Banner is displayed.

layout
{
    area(content)
    {
        group(StandardBanner)
        {
            Caption = '';
            Editable = false;
            Visible = TopBannerVisible and not FinishActionEnabled;
            field(MediaResourcesStd; MediaResourcesStandard."Media Reference")
            {
                ApplicationArea = All;
                Editable = false;
                ShowCaption = false;
            }
        }
        group(FinishedBanner)
        {
            Caption = '';
            Editable = false;
            Visible = TopBannerVisible and FinishActionEnabled;
            field(MediaResourcesDone; MediaResourcesDone."Media Reference")
            {
                ApplicationArea = All;
                Editable = false;
                ShowCaption = false;
            }
        }
        ...
    }
}

var
    MediaRepositoryDone: Record "Media Repository";
    MediaRepositoryStd: Record "Media Repository";
    MediaResourcesDone: Record "Media Resources";
    MediaResourcesStd: Record "Media Resources";
     
trigger OnInit();
begin
    LoadTopBanners();
end;

local procedure LoadTopBanners();
begin
    if MediaRepositoryStd.Get('AssistedSetup-NoText-400px.png',   
       Format(CurrentClientType())) and
       MediaRepositoryDone.Get('AssistedSetupDone-NoText-400px.png', 
       Format(CurrentClientType()))
    then
       if MediaResourcesStd.Get(MediaRepositoryStd."Media Resources Ref") and
          MediaResourcesDone.Get(MediaRepositoryDone."Media Resources Ref")
       then
          TopBannerVisible := MediaResourcesDone."Media Reference".HasValue();
end;