- Basic Information
- Installation and Configuration
- Framework Architecture
- Translation System
- Callbacks and Events
- Templates
- Components
- Forms
- CRUD System
- Database
- Email API
- Token System
- Popup and Nested Forms
- File Upload
- Validation
- Sessions and Security
- Application Lifecycle
- Best Practices
- Troubleshooting
- Sample Project
D2Bridge is an open-source framework that enables converting Delphi or Lazarus applications into web applications without writing any JavaScript code. The framework maintains the native Delphi approach to programming while generating modern applications that run in the browser.
| Parameter | Value |
|---|---|
| Author | Talis Jonatas Gomes |
| License | LGPL 2.1 |
| Beta Version | 2.5.83 |
| Stable Version | 2.0.8 |
| Delphi | 10.0 - 13.0 |
| Lazarus | 3.4 - 4.4 (Windows) |
| talisjonatas@me.com |
| Resource | URL |
|---|---|
| GitHub Repository | https://github.com/d2bridge/d2bridgeframework |
| Discord Server | https://discord.gg/WvHaWP6h9t |
| Official Website | https://d2bridge.com.br |
D2Bridge natively supports 18 languages:
| Code | Language |
|---|---|
AR_SA |
Arabic (Saudi Arabia) |
CS_CZ |
Czech |
DE_DE |
German |
EN_US |
English (USA) |
ES_ES |
Spanish |
FA_IR |
Persian (Iran) |
FR_FR |
French |
IT_IT |
Italian |
JA_JP |
Japanese |
KO_KR |
Korean |
PL_PL |
Polish |
PT_BR |
Portuguese (Brazil) |
RO_RO |
Romanian |
RU_RU |
Russian |
TH_TH |
Thai |
TR_TR |
Turkish |
UK_UA |
Ukrainian |
ZH_CN |
Chinese (Simplified) |
File β New β Other β D2Bridge Framework β D2Bridge Framework Delphi Project
| Parameter | Example | Description |
|---|---|---|
| Name | D2Checkin |
Project name |
| Port | 8888 |
HTTP server port |
| Platform | Web+VCL |
Web, Web+VCL, Web+LCL, Web+FMX |
| Type | Server Console |
Application type |
Project/
βββ wwwroot/ β Public files (HTML, CSS, JS)
β βββ css/
β βββ js/
β β βββ prismpage.js β PrismPage Plugin
β βββ mail/ β Email templates
β βββ temp/ β Session temporary files
βββ language/ β JSON translation files
β βββ PT_BR.json
β βββ EN_US.json
βββ langue_export/ β Translation export (DEBUG)
βββ files/ β Application files (OUTSIDE wwwroot!)
β βββ images/
βββ Units/
βββ D2Checkin_Session.pas β Project class
βββ Unit_DM.pas β DataModule
βββ Unit_ServerController.pas β Server controller
βββ [forms...]
[Database]
Host=localhost
Database=D2Checkin
User=SA
Password=YourPasswordβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β THREADING ARCHITECTURE β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β [HTTP Request] β
β β β
β βΌ β
β βββββββββββββββββββββββ β
β β MAIN THREAD β β Form creation β
β β (visual instance) β (Windows API requirement) β
β βββββββββββββββββββββββ β
β β β
β βΌ β
β βββββββββββββββββββββββ β
β β MULTI-THREAD β β Event handling β
β β (parallelism) β Each button = separate thread β
β βββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Key: Session β Thread. Objects are bound to
TPrismSession, not to thread.
type
TD2Checkin = class(TPrismSessionBase)
public
const FILE_PATH = 'files\';
const FILE_PATH_IMAGES = 'files\images\';
const DEFAULT_USER_IMAGE = 'files\images\default.jpeg';
// User session variables
UserID: Integer;
UserName: string;
UserEmail: string;
UserPassword: string;
UserFotoPath: string;
UserFoto: string; // Base64
AccountID: Integer;
IsLogged: Boolean;
AutoJoinEventID: Integer;
end;// Global access function
function D2Checkin: TD2Checkin;
begin
Result := TD2Checkin(D2BridgeInstance.PrismSession.Data);
end;| Type | Syntax | Example | Usage |
|---|---|---|---|
| Translation | {{_name_}} |
{{_menu_dashboard_}} |
Multilingual text |
| Variable | {{name}} |
{{username}} |
Dynamic data |
| System tag | {{language}} |
- | Current language |
// D2Bridge_Lingua_App_Term.pas
type
TD2BridgeLinguaAppTerm = record
// Menu
menu_dashboard: string;
menu_users: string;
menu_logout: string;
// Buttons
btn_save: string;
btn_cancel: string;
// Messages
MSG_SaveSuccess: string;
MSG_InvalidEmail: string;
end;{
"menu_dashboard": "Dashboard",
"menu_users": "Users",
"menu_logout": "Logout",
"btn_save": "Save",
"btn_cancel": "Cancel",
"MSG_SaveSuccess": "Record saved successfully",
"MSG_InvalidEmail": "Invalid email address"
}1. Add {{_tag_}} tags in HTML
2. Define in D2Bridge_Lingua_App_Term.pas
3. β οΈ COMPILE IN DEBUG MODE (generates JSON)
4. Copy JSON from langue_export/ to language/
5. Edit translations - works at RUNTIME!
// Accessing translations
ShowMessage(D2Bridge.LinguaApp.MSG_SaveSuccess);
// In export
.FormGroup(D2Bridge.LApp.user_name, CSSClass.Col.ColMD6)<!-- Simple callback -->
<a onclick="{{callback=open_dashboard}}">Dashboard</a>
<!-- Callback with parameter -->
<button onclick="{{callback=open_new_account(free)}}">Free</button>
<!-- Callback with multiple parameters -->
<button onclick="{{callback=action(param1=val1¶m2=val2)}}">Action</button>procedure TAdminPageTemplate.Callback(const ACallbackName: string;
AEventParsing: ID2BridgeEventParsing);
begin
// Simple callback
if SameText(ACallbackName, 'open_dashboard') then
begin
if FormDashboard = nil then
FormDashboard := TFormDashboard.Create(nil);
FormDashboard.Show;
end
// Callback with parameter
else if SameText(ACallbackName, 'open_new_account') then
begin
SubscriptionType := AEventParsing.Values['subscription'];
// or first parameter without name:
SubscriptionType := AEventParsing.Values[0];
end;
end;// Close callback
if SameText(ACallbackName, 'close_session') then
Session.Close;
// or Session.Close(false/true);βββββββββββββββββββββββββββββββββββββββββββ
β MASTER TEMPLATE β
β βββββββββββ ββββββββββββββββββββββββ β
β β SIDEBAR β β PAGE TEMPLATE β β
β β MENU β β ($prismpage) β β
β β β β ββββββββββββββββ β β
β β β β β PRISM BODY β β β
β β β β β ($prismbody) β β β
β βββββββββββ ββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββ
# Copy plugin
D2Bridge/Beta/HTML/plugin/prismpage.js β wwwroot/js/prismpage.js<!-- master_template.html -->
<script src="js/prismpage.js"></script>
<PrismPage view-page="dashboard.html"></PrismPage>Benefit: Edit subpages in master template context even without running server!
procedure TFormTemplate.ExportD2Bridge;
begin
inherited;
Title := 'D2 Checkin';
TemplateClassForm := TAdminPageTemplate;
D2Bridge.FrameworkExportType.TemplateMasterHTMLFile := 'master_template.html';
D2Bridge.FrameworkExportType.TemplatePageHTMLFile := 'page_template.html';
end;type
TAdminPageTemplate = class(TD2BridgePrismForm)
protected
procedure Callback(const ACallbackName: string;
AEventParsing: ID2BridgeEventParsing); override;
procedure TagHTML(const ATag: string; var ATagValue: string); override;
end;
procedure TAdminPageTemplate.TagHTML(const ATag: string; var ATagValue: string);
begin
if SameText(ATag, 'username') then
ATagValue := D2Checkin.UserName
else if SameText(ATag, 'user_foto') then
ATagValue := D2Checkin.UserFoto; // Base64
end;procedure TForm_Checkout.ExportD2Bridge;
begin
inherited;
Title := 'My D2Bridge Form';
//TemplateClassForm := TD2BridgeFormTemplate;
D2Bridge.FrameworkExportType.TemplateMasterHTMLFile := '';
D2Bridge.FrameworkExportType.TemplatePageHTMLFile := '';
with D2Bridge.Items.Add do
begin
with Row.Items.Add do
with ColAuto.Items.Add do
begin
VCLObj(Label_TagName);
VCLObj(DBText_TagName);
end;
with Row.Items.Add do
Col8.Add.LCLObj(Image_Product);
end;
end;// Row with columns
with D2Bridge.Items.Add do
begin
Row.Items.Add.VCLObj(EditFirstName, CSSClass.Col.ColMD6);
Row.Items.Add.VCLObj(EditLastName, CSSClass.Col.ColMD6);
end;
// Row with Bootstrap margins
with D2Bridge.Items.Add.Row('mt-2 mb-2') do // margin-top, margin-bottom
begin
Row.Items.Add.Image(ImageFoto, CSSClass.Col.ColMD4);
Row.Items.Add.FileUpload(UploadFoto, CSSClass.Col.ColMD8);
end;| Class | Description |
|---|---|
ColMD1 - ColMD12 |
1-12 units on medium+ |
ColLG1 - ColLG12 |
1-12 units on large+ |
ColSize1 - ColSize12 |
Fixed width |
with D2Bridge.Items.Add.PanelGroup('{{_personal_data_}}', 'PanelUserData',
CSSClass.Col.ColLG12) do
begin
AddFormGroup('{{_name_}}', CSSClass.Col.ColLG4).AddVCLObj(DBEditName);
AddFormGroup('{{_email_}}', CSSClass.Col.ColLG4).AddVCLObj(DBEditEmail);
AddFormGroup('{{_phone_}}', CSSClass.Col.ColLG4).AddVCLObj(DBEditPhone);
end;with Card do
begin
CSSClasses := CSSClass.Card.Card_Center_ExtraLarge;
Header('My Text');
with BodyItems.Add do
begin
with Row.Items.Add do
begin
Col6.Add.FormGroup(Label_FullName).AddLCLObj(DBEdit_FullName, 'ValidationAccount', true);
Col6.Add.FormGroup(Label_Doc).AddLCLObj(DBEdit_Doc);
end;
// ...
end;
with Footer.Items.Add do
with Row.Items.Add do
begin
ColAuto.Add.LCLObj(Button_Save, 'ValidationAccount', false, CSSClass.Button.save);
end;
end;with D2Bridge.Items.Add do
begin
with HTMLDIV('myClass').Items.Add do
begin
// Div content
VCLObj(Component);
end;
end;with D2Bridge.Items.Add.Accordion do
begin
// Section expanded by default
with Items.Add('Photos', True) do
Items.Add.Image(Image1);
// Section collapsed by default
with Items.Add('Advanced Options', False) do
Items.Add.VCLObj(EditAdvanced);
end;// Carousel with DataSource - ONE LINE!
with Row.Items.Add.Div(CSSClass.Col.ColMD4) do
begin
Carousel
.DataSource(DSEventPhoto)
.FieldName('foto_path');
end;
// Configuration
with Carousel do
begin
DataSource(DSEventPhoto);
FieldName('foto_path');
Interval := 3000; // ms between slides
MaxRecords := 25; // max images
ShowIndicators := True; // indicator dots
ShowControls := True; // prev/next buttons
AutoPlay := True; // auto-scroll
end;Turns any VCL component into a clickable link:
// Regular component
.AddVCLObj(DBTextAdminName);
// Component as LINK
.AddVCLObjLink(DBTextAdminName);// Click handling
procedure TFormAccount.DBTextAdminNameClick(Sender: TObject);
begin
// Open popup
D2D.ShowPopup('PopupUserAdmin');
end;File β New β Other β D2Bridge Framework β D2Bridge Form
File β New β Other β D2Bridge Framework β D2Bridge Inherited Form
β Select Ancestor: TFormTemplate
TFormTemplate (Master/Page)
β
βββ TFormDashboard
β
βββ TFormCrudTemplate
β
βββ TFormUsers
βββ TFormEvents
βββ TFormAccount
procedure TFormDashboard.ExportD2Bridge;
begin
// β οΈ In inherited forms COMMENT OUT inherited!
// inherited; // Master and Page already in parent!
D2Bridge.FrameworkExportType.TemplatePageHTMLFile := 'dashboard.html';
end;1. Create β Instance creation
2. ExportD2Bridge β Component export
3. OnShow β Before rendering (open Query)
4. BeginRender β Start rendering
5. [Component rendering]
6. EndRender β End rendering (PrismControlFromID!)
7. [Send HTML to browser]
8. OnActivate β After loading in browser
| Event | When to use | PrismControl available? |
|---|---|---|
OnShow |
Opening Query, data | β NO |
BeginRender |
Before render | β NO |
EndRender |
PrismControl manipulation | β YES |
OnActivate |
After page load | β YES |
βββββββββββββββββββββββββββββββββββββββββββ
β CARD SEARCH (Search) β
β βββ Crud_RowSearch (buttons) β
β βββ Crud_RowGrid (table) β
βββββββββββββββββββββββββββββββββββββββββββ€
β CARD DATA (Edit) β
β βββ Form fields β
βββββββββββββββββββββββββββββββββββββββββββ
type
TFormUsers = class(TFormCrudTemplate)
protected
procedure OnCrudOpen(Sender: TObject); override;
procedure OnCrudSearch(Sender: TObject); override;
procedure OnCrudEdit(Sender: TObject; var AAllow: Boolean); override;
procedure OnCrudInsert(Sender: TObject; var AAllow: Boolean); override;
procedure OnCrudSave(Sender: TObject; var AAllow: Boolean); override;
procedure OnCrudDelete(Sender: TObject; var AAllow: Boolean); override;
procedure OnCrudBack(Sender: TObject); override;
procedure OnCrudClose(Sender: TObject); override;
end;procedure TFormUsers.OnCrudOpen(Sender: TObject);
begin
CrudOperation(coSearch);
end;
procedure TFormUsers.OnCrudSearch(Sender: TObject);
begin
DM.QueryUsers.Close;
DM.QueryUsers.SQL.Text :=
'SELECT * FROM users WHERE id_account = ' + D2Checkin.AccountID.ToString;
DM.QueryUsers.Open;
end;
procedure TFormUsers.OnCrudSave(Sender: TObject; var AAllow: Boolean);
begin
AAllow := True;
// Validation
if not TD2BridgePoni.IsValidAddress(DBEditEmail.Text) then
begin
D2D.Validation(DBEditEmail, False, D2Bridge.LApp.MSG_InvalidEmail);
AAllow := False;
Exit;
end;
end;CrudOperation(coSearch); // Search
CrudOperation(coEdit); // Edit
CrudOperation(coInsert); // Insert
CrudOperation(coSave); // Save
CrudOperation(coDelete); // Delete
CrudOperation(coBack); // BackCrudStartCard := csSearch; // Start from list
CrudStartCard := csData; // Start from edit (e.g., Profile)type
TCrudPermission = set of (cpSearch, cpEdit, cpInsert, cpSave, cpDelete);
CrudPermissions := [cpSearch, cpEdit, cpInsert, cpSave, cpDelete]; // Full
CrudPermissions := [cpSearch]; // View onlyprocedure TFormEvents.InitControlsD2Bridge(const PrismControl: TPrismControl);
begin
inherited;
if PrismControl.VCLComponent = DBGridSearch then
begin
// Add column with buttons
with PrismControl.Columns.Add do
begin
Index := 0;
Width := 78; // ~26px per button
// View button
with Buttons.Add do
begin
ButtonModel := bmView;
Caption := '';
OnClick := ShowEvent;
end;
// Edit button
with Buttons.Add do
begin
ButtonModel := bmEdit;
Caption := '';
OnClick := procedure begin CrudOperation(coEdit); end;
end;
// Delete button
with Buttons.Add do
begin
ButtonModel := bmDelete;
Caption := '';
OnClick := procedure begin CrudOperation(coDelete); end;
end;
end;
end;
end;unit Unit_DM;
uses D2Bridge.Instance;
type
TDM = class(TDataModule)
ADOConnection: TADOConnection;
QueryUser: TADOQuery;
QueryAccount: TADOQuery;
DSUser: TDataSource;
end;
function DM: TDM;
implementation
function DM: TDM;
begin
Result := TDM(D2BridgeInstance.GetInstance(TDM));
end;uses
Unit_DM,
Winapi.ActiveX; // Required for SQL Server!
procedure TD2Checkin.OpenDM;
begin
CoInitializeEx(0, COINIT_MULTITHREADED); // SQL Server only!
if DM = nil then
D2BridgeInstance.CreateInstance(TDM);
end;procedure TDM.ADOConnectionWillConnect(Connection: TADOConnection;
var ConnectionString, UserID, Password: WideString;
var ConnectOptions: TConnectOption; var EventStatus: TEventStatus);
var
IniFile: TIniFile;
begin
IniFile := TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'Config.ini');
try
ConnectionString :=
'Provider=SQLOLEDB.1;' +
'Password=' + IniFile.ReadString('Database', 'Password', '') + ';' +
'User ID=' + IniFile.ReadString('Database', 'User', 'SA') + ';' +
'Initial Catalog=' + IniFile.ReadString('Database', 'Database', 'D2Checkin') + ';' +
'Data Source=' + IniFile.ReadString('Database', 'Host', 'localhost');
finally
IniFile.Free;
end;
end;Location: clUseServer (Cursor Location = Server)
CursorType: ctKeySet (Cursor Type = KeySet)
procedure TServerController.ConfigEmail;
begin
if D2BridgeManager.API.Mail.Config then
begin
Config.Host := 'smtp.gmail.com';
Config.Port := 587;
Config.Username := 'email@gmail.com';
Config.Password := 'xxxx xxxx xxxx xxxx'; // App Password!
Config.UseSSL := True;
Config.UseTLS := True;
Config.UseThread := True;
Config.FromName := 'D2 Checkin';
Config.FromMailAddress := 'noreply@d2checkin.com';
end;
end;libeay32.dll
ssleay32.dll
procedure TD2Checkin.SendEmail(const ATo, ASubject, ABody: string);
begin
with D2BridgeServerController.API.Mail do
begin
Addresses.Clear;
Addresses.Add(ATo);
Subject := ASubject;
Body.Text := ABody;
if not Send then
raise Exception.Create('Email sending error');
end;
end;type
TTokenType = (
ttNewUser, // New user (email verification)
ttRecoverPass, // Password recovery
ttNewEvent, // New event
ttCheckin // Check-in
);
TTokenMode = (
tmLink, // Validation by link (64 characters)
tmCode // Validation by code (6 digits)
);const
TOKEN_LINK_SIZE = 64;
TOKEN_CODE_SIZE = 6;
TOKEN_LINK_EXPIRY_HOURS = 24;
TOKEN_CODE_EXPIRY_SECONDS = 300;function TD2Checkin.CreateToken(AType: TTokenType; AMode: TTokenMode;
AUserID: Integer; AEventID: Integer = 0): Integer;
var
TokenValue: string;
begin
repeat
if AMode = tmLink then
TokenValue := GenerateRandomString(TOKEN_LINK_SIZE)
else
TokenValue := GenerateRandomNumber(TOKEN_CODE_SIZE);
until not TokenExists(TokenValue);
with DM.QueryToken do
begin
Append;
FieldByName('user_id').AsInteger := AUserID;
FieldByName('id_event').AsInteger := AEventID;
FieldByName('type').AsString := TokenTypeToStr(AType);
FieldByName('token').AsString := TokenValue;
FieldByName('created_at').AsDateTime := Now;
FieldByName('expires_at').AsDateTime := Now + (TOKEN_LINK_EXPIRY_HOURS / 24);
Post;
Result := FieldByName('id').AsInteger;
end;
end;// In export
with D2Bridge.Items.Add.Popup('PopupName', 'Title', False) do
begin
// False = show X button
// True = hide X button
Items.Add.VCLObj(Component1);
Items.Add.VCLObj(Component2);
end;// Show
D2D.ShowPopup('PopupName');
// Hide
D2D.ClosePopup('PopupName');A Nested Form is a form embedded in another form or popup.
type
TFormAccount = class(TFormTemplate)
private
FormUsers: TD2BridgeForm; // β οΈ Base type (avoid circular reference!)
end;
procedure TFormAccount.ExportD2Bridge;
begin
inherited;
// Creating Nested
if FormUsers = nil then
begin
FormUsers := TFormUsers.Create(Self);
TFormUsers(FormUsers).CrudStartCard := csData;
D2D.AddNested(FormUsers);
end;
// Popup with Nested
with D2Bridge.Items.Add.Popup('PopupUserAdmin', D2Bridge.LApp.edit_user, False) do
begin
Items.Add.AddNested(FormUsers);
end;
end;<!-- Before </body> -->
<PrismPopup name="PopupShowEvent"></PrismPopup>// Export
Row.Items.Add.FileUpload(UploadFoto, CSSClass.Col.ColMD8);
// Event
procedure TFormUsers.UploadFotoUpload(Sender: TObject);
var
UploadedFile, NewFileName: string;
begin
UploadedFile := UploadFoto.UploadFiles[0];
// Generate unique name (cache busting!)
NewFileName := D2Checkin.FILE_PATH_IMAGES +
'user_' + UserID.ToString + '_' +
GenerateRandomString(8) +
ExtractFileExt(UploadedFile);
// Copy new one
CopyFile(PChar(UploadedFile), PChar(NewFileName), False);
// Load preview
ImageFoto.Picture.LoadFromFile(NewFileName);
end;// Export with limit
with Row.Items.Add.FileUpload(UploadImages, CSSClass.Col.ColMD12) do
begin
MaxFiles := 5; // Max 5 files
MaxFileSize := 20; // Max 20 MB per file
Accept := 'image/*'; // Images only
end;uses D2Bridge.Poni;
if not TD2BridgePoni.IsValidAddress(EditEmail.Text) then
begin
D2D.Validation(EditEmail, False, D2Bridge.LApp.MSG_InvalidEmail);
Abort;
end;procedure TFormAccount.InitControlsD2Bridge(const PrismControl: TPrismControl);
begin
inherited;
// CNPJ mask (Brazil)
if PrismControl.VCLComponent = DBEditDocument then
TDBEdit(PrismControl.VCLComponent).EditMask := TD2BridgePrismTMask.BrasilCNPJ;
// Custom mask
if PrismControl.VCLComponent = DBEditPhone then
TDBEdit(PrismControl.VCLComponent).EditMask :=
'{"mask": "(99) 99999-9999", "autoUnmask": true}';
end;// ServerController.pas
procedure TServerController.NewSession(Sender: TObject);
begin
D2Checkin.IsLogged := False;
D2Checkin.AutoJoinEventID := 0;
end;procedure TFormLogin.ButtonLoginClick(Sender: TObject);
begin
// Validation...
// On success:
D2Checkin.IsLogged := True;
D2Checkin.UserID := DM.QueryUser.FieldByName('id').AsInteger;
FormDashboard.Show;
end;// Ends EVERYTHING: threads, forms, DM, variables
Session.Close;
// or Session.Close(false/true);wwwroot/ β Accessible from browser
files/ β NOT accessible from browser!
Create β ExportD2Bridge β OnShow β BeginRender β
[Rendering] β EndRender β InitControlsD2Bridge β
[Send to browser] β OnActivate
| Event | Usage |
|---|---|
OnShow |
Opening Query, setting data |
BeginRender |
Preparation before render |
EndRender |
D2D.PrismControlFromID() |
InitControlsD2Bridge |
Masks, GRID formatting |
OnActivate |
User questions, auto-actions |
// β NEVER in OnShow/BeginRender/EndRender:
ShowMessage('Question?', mtConfirmation, [mbYes, mbNo]);
// Will block session!
// β
Only in OnActivate:
procedure TForm.FormActivate(Sender: TObject);
begin
if ShowMessage('Continue?', mtConfirmation, [mbYes, mbNo]) = mrYes then
// ...
end;β
DEBUG β Generates JSON translations
β
RELEASE β Production
uses
// ...other units...
D2Bridge.Forms; // β ALWAYS LAST!EmailBody.LoadFromFile(Path, TEncoding.UTF8);// WRONG - components not rendered yet
procedure TForm.FormShow(Sender: TObject);
begin
DM.Query.Open; // DBLookup won't work!
end;
// CORRECT
procedure TForm.FormActivate(Sender: TObject);
begin
DM.Query.Open; // Now it works!
end;// WRONG
FormUsers: TFormUsers; // Concrete type
// CORRECT
FormUsers: TD2BridgeForm; // Base type
TFormUsers(FormUsers).Property := Value; // Castprocedure TFormLogin.FormActivate(Sender: TObject);
begin
if DebugHook <> 0 then
begin
EditEmail.Text := 'test@test.com';
EditPassword.Text := 'password';
end;
end;D2Bridge supports encrypted TLS connections. To enable TLS, you must:
- Add
IdSSLOpenSSLHeadersto yourusesclause. - Point OpenSSL to the directory containing the required DLLs (
ssleay32.dllandlibeay32.dll):
uses
IdSSLOpenSSLHeaders;
// Set the path to SSL libraries (must match your target architecture)
IdOpenSSLSetLibPath('C:\Path\To\SSL\DLLs');Note: TLS will not work if
IdSSLOpenSSLHeadersis missing from theusesclause or if the SSL library path is not set correctly.
To enable automatic translation of built-in GUI navigation elements (e.g. button captions), use context-aware translation tags in your captions:
{{_Button,CaptionOpen_}}
{{_Button,CaptionRefresh_}}
Then add D2Bridge.Lang.Core to your uses clause and override TagTranslate:
uses
D2Bridge.Lang.Core;
procedure TForm1.TagTranslate(const Language: TD2BridgeLang;
const AContext: string; const ATerm: string; var ATranslated: string);
begin
inherited;
ATranslated := D2BridgeLangCore.LangByTD2BridgeLang(Language)
.Language.Translate(AContext, ATerm);
end;Cause: Normal in debug mode when closing threads.
Solution: Ignore in debug, doesn't appear in release.
Cause: Query opened in OnShow instead of OnActivate.
Solution: Move Query.Open to OnActivate.
Cause: Browser cache.
Solution: Add random string to filename.
Cause: Called in OnShow instead of EndRender.
Solution: Move to EndRender or OnActivate.
Cause: Missing <PrismPopup> tag in HTML.
Solution: Add before </body>:
<PrismPopup name="PopupName"></PrismPopup>Cause: No favicon.ico file in the wwwroot/ directory. The framework issues a 301 redirect to https://d2bridge.com.br/favicon.ico.
Solution: Place your own favicon.ico file in the wwwroot/ directory.
Event management system with participant check-in.
- β Translation system (18 languages)
- β Callbacks with parameters
- β Master/Page Template
- β CRUD with inheritance
- β Single and multiple upload
- β Field masks
- β Link component
- β Nested Forms
- β Popup
- β Carousel
- β Tokens
- β Toast
- β Clipboard
- β GRID formatting
- β Validation
- β Email API
"Develop web the Delphi way"
D2Bridge Framework - LGPL 2.1
