Form management to speedup app

Took quite a bit of fiddling but I've put together a demo project for you (or anyone else) to show forms that are created at runtime (once) and then swapped in and out of a main div.

In the demo, all the forms are visible (and functioning) at the same time. So when you click on the button at the bottom, it is actually the button on the form itself - just displayed in a smaller div that acts as a placeholder. Clicking on each of the buttons basically just swaps the forms between their original placeholders and the main form viewing div. Naturally in a real project the placeholders don't need to be visible and the display div can take up the whole screen.

The code for the buttons is pretty much the same on each form, so it could be turned into a common function easily enough I'm sure. And there are likely a thousand ways to do this kind of thing, or even do it the same way with prettier code. But it works well enough I think.

Hopefully it gives you some ideas as to how this kind of approach can work in your project:

FormTest.zip (224.7 KB)

And a video in case anyone wants to see what it looks like without the hassle of running the project:

formtest.mpeg

The main form code looks like this.

unit UnitMain;

interface

uses
  System.SysUtils, System.Classes, JS, Web, WEBLib.Graphics, WEBLib.Controls,
  WEBLib.Forms, WEBLib.Dialogs, Vcl.Controls, Vcl.StdCtrls,
  WEBLib.StdCtrls, WEBLib.ExtCtrls, WEBLib.WebCtrls;

type
  TFormMain = class(TWebForm)
    WebPanelMain: TWebPanel;
    WebMemo1: TWebMemo;
    WebPanelTop: TWebPanel;
    WebLabelMain: TWebLabel;
    WebButtonMain: TWebButton;
    WebPanelCollection: TWebPanel;
    WebGridPanel1: TWebGridPanel;
    WebPanelHolder: TWebPanel;
    Panel1: TWebPanel;
    WebHTMLDiv1: TWebHTMLDiv;
    Panel2: TWebPanel;
    WebHTMLDiv2: TWebHTMLDiv;
    Panel3: TWebPanel;
    WebHTMLDiv3: TWebHTMLDiv;
    Panel4: TWebPanel;
    WebHTMLDiv4: TWebHTMLDiv;
    procedure WebFormCreate(Sender: TObject);
    [async] procedure WebButtonMainClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    Form1 :TWebForm;
    Form2 :TWebForm;
    Form3 :TWebForm;
    Form4 :TWebForm;
    CurrentForm: TWebForm;
    CurrentFormElement: String;
    CurrentFormSource: String;
  end;

var
  FormMain: TFormMain;

implementation

uses
  Unit1, Unit2, Unit3, Unit4;

{$R *.dfm}


procedure TFormMain.WebButtonMainClick(Sender: TObject);

  procedure AfterCreate(AForm: TObject);
  begin
    WebMemo1.Lines.Add((AForm as TWebForm).Caption+' Created');

    if (AForm as TWebForm).Caption = 'Form1' then
    begin
      WebMemo1.Lines.Add('Showing Form1');
      CurrentForm := Form1;
      CurrentFormElement := 'WebHTMLDiv1';
      CurrentFormSource := 'FormHolder1';
      asm
        var form = document.getElementById("WebHTMLDiv1");
        document.getElementById("FormHolderMain").append(form);
        setTimeout(() => { window.dispatchEvent(new Event('resize')); }, 0);
      end;
    end;
  end;

begin

  if not(Assigned(Form1)) then
  begin
    WebMemo1.Lines.Add('Creating Form1');
    Application.CreateForm(TForm1, WebHTMLDiv1.ElementID, Form1, @AfterCreate);
  end;

  if not(Assigned(Form2)) then
  begin
    WebMemo1.Lines.Add('Creating Form2');
    Application.CreateForm(TForm2, WebHTMLDiv2.ElementID, Form2, @AfterCreate);
  end;

  if not(Assigned(Form3)) then
  begin
    WebMemo1.Lines.Add('Creating Form3');
    Application.CreateForm(TForm3, WebHTMLDiv3.ElementID, Form3, @AfterCreate);
  end;

  if not(Assigned(Form4)) then
  begin
    WebMemo1.Lines.Add('Creating Form4');
    Application.CreateForm(TForm4, WebHTMLDiv4.ElementID, Form4, @AfterCreate);
  end;

end;

procedure TFormMain.WebFormCreate(Sender: TObject);
begin
  WebButtonMainClick(Sender);
end;

end.

And the forms (they're all the same basically) look like this.

unit Unit1;

interface

uses
  System.SysUtils, System.Classes, JS, Web, WEBLib.Graphics, WEBLib.Controls,
  WEBLib.Forms, WEBLib.Dialogs, Vcl.StdCtrls, WEBLib.StdCtrls,
  Vcl.Controls, WEBLib.ExtCtrls;

type
  TForm1 = class(TWebForm)
    WebPanel1: TWebPanel;
    WebButton10: TWebButton;
    WebMemo10: TWebMemo;
    procedure WebButton10Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses
  UnitMain;

{$R *.dfm}



procedure TForm1.WebButton10Click(Sender: TObject);
var
  Element: String;
  Source: String;
begin
  if Assigned(FormMain.CurrentForm) then
  begin
    if (FormMain.CurrentForm <> FormMain.Form1) then
    begin

      FormMain.WebMemo1.Lines.Add('Hiding '+(FormMain.CurrentForm as TWebForm).Caption);

      // Local variables to use in JS
      Element := FormMain.CurrentFormElement;
      Source  := FormMain.CurrentFormSource;

      // Assignments for new form
      FormMain.CurrentForm        := FormMain.Form1;
      FormMain.CurrentFormElement := 'WebHTMLDiv1';
      FormMain.CurrentFormSource  := 'FormHolder1';

      // Hide currently shown form
      asm
        var oldform = document.getElementById(Element);
        document.getElementById(Source).append(oldform);

        var newform = document.getElementById('WebHTMLDiv1');
        document.getElementById('FormHolderMain').append(newform);

        setTimeout(() => { window.dispatchEvent(new Event('resize')); }, 0);
      end;

     FormMain.WebMemo1.Lines.Add('Showing '+(FormMain.CurrentForm as TWebForm).Caption);
    end;
  end;
end;

end.

The main project source looks like this (updated from the zip file, but functionally the same).

program Project1;

uses
  Vcl.Forms,
  WEBLib.Forms,
  UnitMain in 'UnitMain.pas' {FormMain: TWebForm} {*.html},
  Unit1 in 'Unit1.pas' {Form1: TWebForm} {*.html},
  Unit2 in 'Unit2.pas' {Form2: TWebForm} {*.html},
  Unit3 in 'Unit3.pas' {Form3: TWebForm} {*.html},
  Unit4 in 'Unit4.pas' {Form4: TWebForm} {*.html};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TFormMain, FormMain);
//  Application.CreateForm(TForm1, Form1);
//  Application.CreateForm(TForm2, Form2);
//  Application.CreateForm(TForm3, Form3);
//  Application.CreateForm(TForm4, Form4);
  Application.Run;
end.

So none of the subforms are created until needed, but they only need to be created once.

1 Like