Forms
In TMS WEB Core, the base class for forms is TWebForm.TWebForm
is similar to a TForm
in the VCL. Controls can be put at design time on the TWebForm
and will be displayed. The TWebForm
is by default displayed as a full page in the browser. In addition to the controls that the form hosts that are created at design-time or at runtime, there is also the HTML code associated with the form. This HTML can be an empty HTML BODY when all controls are created by Delphi classes or it can contain additional HTML elements or HTML elements to which Delphi classes are mapped.
The default project looks like:
and you see under unit1.pas
not only a reference to the DFM
file where Delphi class properties are stored but also the HTML file associated with the form in Unit1
. The default HTML for this form can be opened & edited from the Delphi IDE but can also be ‘designed' by any other tool for creating HTML files. The default content of the HTML file is:
In the default HTML files, the BODY is empty and the controls defined in Delphi will be put in the BODY upon creation of the form instance. The application creates the main form in the same way as in a VCL application, i.e. with the code:
It is also possible that the Delphi controls will be created within another HTML element than the HTML BODY element.
If unit1.html
contains:
we can specify at form class level Form.FormContainer: string and set this to the HTML element ID of the HTML element in which the form should be rendered, i.e. in this case it could be set to “form”.
Alternatively, there are also forms in the project that have not HTML template file. These are added to the project via the IDE wizard and selecting TMS WEB Direct Form:
This appears in the project manager as:
The big difference here is that when the application opens this form via
no additional HTML file needs to be loaded and the form will use the HTML as specified in the application HTML file. This type forms as such loads faster. It does not need a server to return the form specific HTML file (meaning such project can also be directly started by double-clicking the application HTML file fromWindows Explorer
). If you want to use HTML elements linked to form controls, these HTML elements will need to be present in the main application HTML file.
As such, when wanting to use this type direct form for applications with multiple forms, it will
require a different application management code to handle the HTML file ( possibly programmatically).
Creating forms at runtime
Due to the asynchronous behaviour of loading the HTML for a form, the creation of a form in code is slightly different in the web than in VCL. To create a form, following code can be used:
procedure TForm1.WebButton1Click(Sender: TObject);
var
newform: TForm2;
// async called when the form is closed (via form.Close method where
ModalResult can be set)
procedure AfterShowModal(AValue: TModalResult);
begin
ShowMessage('Form 2 closed with new value:'+newform.frm2Edit.Text);
WebEdit1.Text := newform.frm2Edit.Text;
end;
// async called OnCreate for TForm2
procedure AfterCreate(AForm: TObject);
begin
(AForm as TForm2).frm2Edit.Text := WebEdit1.Text;
end;
begin
newform := TForm2.CreateNew(@AfterCreate);
newform.ShowModal(@AfterShowModal);
end;
An alternative way to create forms is using equivalent functions that use promises. With this approach, code can be written as if it is sequential but still, in execution it is asynchronous. The equivalent code to create a form using promises and await() is
procedure TForm1.WebButton1Click(Sender: TObject);
var
newform: TForm2;
begin
newform := TForm2.Create(Self);
// load file HTML template + controls await(TForm2, newform.Load());
// init control after loading newform.frm2Edit.Text := WebEdit1.Text;
try
// excute form and wait for close
await(TModalResult, newform.Execute);
ShowMessage('Form 2 closed with new value:"'+newform.frm2Edit.Text+'"');
WebEdit1.Text := newform.frm2Edit.Text;
finally
newform.Free;
end;
end;
Note that there is one additional important difference to make the promise/await based
approach work, and that is to make the form method WebButton1Click
as async. This can be
done via an attribute:
TForm2
will replace the page showing the actual form. When this form
is closed, the original form from where TForm2 is shown, will be displayed in the browser page
again. The procedure AfterCreate
is shown when the HTML for TForm2
is loaded and its
controls are created. The ShowModal()
method will display the actual form in the browser page
and a reference to the method that will be called when the form is closed can be passed as
parameter as ShowModal
is not a blocking method, as such blocking methods are not possible
in a browser environment.
In addition to forms displayed in the full browser page, it is also possible to create popup forms.
These forms will be displayed on top of other forms, effectively disabling the forms on top of which the new form is displayed till this new form is closed. To display a form as popup, all that is needed is setting form.Popup = true
.
Example:
begin
newform := TForm2.CreateNew(@AfterCreate);
newform.Popup := true;
newform.PopupOpacity := 0.2; // only needed when main form should
// remain visible under a layer with
// opacity
newform.ShowModal(@AfterShowModal);
end;
For popup forms, 2
more settings are relevant.
The popup form can have a caption or not. When the popup form has a caption, the user will be able ot move the popup form on the screen via the caption. The caption of the form is set via WebForm.Caption
: string;
The popup form can be resizable (on desktop browsers) via a resizer area in the bottom-right corner of the form.
These extra form settings are done via the TWebForm.Border
property:
WebForm.Border setting | Description |
---|---|
fbDialogSizeable | Popup form has caption and can be sized |
fbDialog | Popup form has caption and has a fixed size |
fbSingle | Not sizeable form, no caption |
Hosting forms in other controls
Finally, it is also possible to embed other forms in controls or HTML elements in other forms.
To do so, create the form with overloads of the CreateForm
method of the Application object or via the CreateNew
constructor overload of TWebForm:
Via the TApplication
object:
procedure CreateForm(AInstanceClass: TWebFormClass; AElementID: string; var AReference); overload;
procedure CreateForm(AInstanceClass: TWebFormClass; AElementID: string; var AReference; AProc: TFormCreatedProc); overload;
The AInstanceClass
is the class type of the form to be created. The AElementID
is the ID of the HTML element (or Delphi class control ID) that is the HTML container in which the form will be created. The AReference
is a reference to the form instance that will be created and optionally a referene to a procedure that will be called when the form was effectively created can be passed.
Via the TWebForm CreateNew
overload:
The AElementID is the ID of the HTML element (or Delphi class control ID) that is the HTML container in which the form will be created. Optionally a method can be passed that will be called when the form was created.
Example code:
In this sample code, a new form of the type TSubForm is created. The form will be displayed inside a panel on the form as we use the panel's HTML element ID. When the form is created, and this all controls on the form are accessible, the AfterCreate()
procedure is called.
Overview of TWebForm properties, methods, events:
Properties
Property | Description |
---|---|
ActiveControl: TCustomControl | Get and set the focused/active control on the form |
Caption: string | Sets the form caption. For a regular form, this is the browser title text, for a popup form, this is the text in the form caption area |
CaptionElement: TJSHTMLElement | Read-only property giving access to the HTML element used for the form caption |
Color | Sets the background color of the form |
CSSLibrary: TCSSLibrary | Can be: - cssNone - cssBootstrap Selects between using a default Bootstrap CSS library use for the form or no default CSS library. When CSSLibrary is set to cssBootstrap , adding new controls at design-time on the form, will automatically preset the control’s ElementClassName property to the best matching Bootstrap class for the control. |
ElementCaptionClasssName | CSS class for the form caption DIV element, allows to use CSS to customize the caption element |
FormContainer: TElementID | Sets the ID of the HTML element in the form HTML template serving as the container of the entire form |
FormFileName: string | Holds the filename of the HTML template for the form. By default this is the unit name with extension .HTML |
FormStyle: TFormStyle | Unused property for backwards compatibility with VCL forms |
Menu: TCustomControl | Sets the main menu for the form |
ModalResult: TModalResult | Holds the modal result when the form closes |
Popup: Boolean | When true, the form will be shown as popup dialog over the parent form, otherwise it will be displayed in the entire browser window. |
PopupOpacity: single | Sets the opacity of the layer making the parent form UI elements inaccessible while a popup form is shown |
ShowClose: Boolean | When true, a close button is shown in the caption right corner of a form displayed as popup form |
Shadow: boolean | When true, the popup form is shown with a shadow border over the parent form |
Methods
Method | Description |
---|---|
AddCSS(const id: string; const CSS: string); A | Adds new CSS code to the form. The CSS code is added in the STYLE section of the document with given id. |
Close | Closes the form |
Execute: TJSPromise | Async method called to show a form modally, waiting for it to be closed |
Load: TJSPromise | Async method loading the form HTML template |
RemoveCSS(id: string); | Removes the CSS style element with id |
SelectFirst | Sets focus to the first element on the form |
SelectNext(CurControl: TControl; GoForward: Boolean = true) | Sets the focus to the next element on the form (or previous element when GoForward = false) |
ShowModal(AProc: TModalResultProc = nil) | Shows a form modally and calls the anonymous method returning the modal result when the form is closed |
UpdateCSS(const id: string; const CSS: string) | Updates the CSS style information for CSS style element id. |
Events
Event | Description |
---|---|
OnClick: TClickEvent | Event triggered when the form is clicked |
OnClose: TCloseEvent | Event triggered when the form is closed |
OnCloseQuery: TCloseQueryEvent | Event triggered just before the form is about the be closed. Can be used to prevent actual closing of the form via the CanClose parameter |
OnCreate: TNotifyEvent | Event triggered when the form instance was created |
OnDestroy: TNotifyEvent | Event triggered when the form is destroyed |
OnDeactivate: TNotifyEvent | |
OnDblClick: TNotifyEvent | Event triggered when the form is doubleclicked |
On DOMContentLoaded | Event triggered when the form’s HTML template fully finished loading in the browser DOM |
OnHashChange: THashChangeEvent | Event triggered when the browser navigation hash changed |
OnOrientationChange: TOrientationChangeEvent | Event triggered when the page orientation changed, typically happening on a mobile device |
OnPaint: TOnPaintEvent | Event added for compatibility with a VCL form |
OnResize: TNotifyEvent | Event triggered when the form resizes due to the browser window being resized |
OnScroll: TNotifyEvent | Event triggered when there is scrolling of the form in the browser window |
OnShow: TNotifyEvent | Event triggered when the form is shown |
OnUnload: TNotifyEvent | Event triggered when the browser unloaded the HTML associated with the form |
Form inheritance
Just like in a Delphi VCL application, TMS WEB Core web client applications can also work with the concept of visual form inheritance. This means that a TWebForm
can be created, UI
controls and UI
control logic can be applied to this form and then a form descending from this base form class can be created. The difference with a VCL application form is that for a TWebForm
, there is also an associated HTML template. As each form has a HTML template, when creating a new descending form, a new HTML template will be created. Note that for a descending form, the HTML template belonging to the descending form will be used to render the form rather than the HTML template belonging to the base form.
The process to create a descending form is done from the context menu in the Delphi IDE project manager:
Frames
In a TMS WEB Core application, the concept for frames can also be used. Frames can encapsulate specific UI control logic in combination with UI controls. A frame in a TMS WEB Core application has no associated HTML template. The template of the form hosting the frame is used. To create a new frame, follow the same steps as for adding a new VCL frame. After the frame is added to the project, TMS WEB Core components can be dropped on the frame and the UI control logic can be written in the frame unit. Then, to use the frame, enter ‘Frames’ on the object inspector and select the frame you want to add to a form from the frames list