A functional fix including passing parameters could look like this:
diff --git a/WEBLib.Forms.orig.pas b/WEBLib.Forms.fix.pas
index 380953c..49d402c 100644
--- a/WEBLib.Forms.orig.pas
+++ b/WEBLib.Forms.fix.pas
@@ -277,6 +277,7 @@ type
FOnDOMContentLoaded: TNotifyEvent;
FShowClose: boolean;
FOnHashChange: THashChangeEvent;
+ FQueryString: string;
procedure SetModalResult(const Value: TModalResult);
function GetFormStyle: TFormStyle;
procedure SetFormStyle(const Value: TFormStyle); virtual;
@@ -366,6 +367,7 @@ type
procedure CreateInitialize; override;
constructor Create(id: string); overload; override;
constructor Create(id: string; var AReference); overload; virtual;
+ constructor Create(id, query: string; var AReference); overload; virtual;
constructor Create(AOwner: TComponent); overload; override;
constructor Create(AOwner: TComponent; IsPopup: boolean; ABorder: TFormBorderStyle = fbSingle; ATitle: string = ''); overload;
constructor CreateNew(AOwner: TComponent; Dummy: Integer = 0); overload; virtual;
@@ -717,6 +719,7 @@ type
FHotReloadVersion: Integer;
FHotReloadFile: string;
{$ENDIF}
+ FQueryString: string;
function DoFormLoad(Event: TEventListenerEvent): boolean;
function DoFormAbort(Event: TEventListenerEvent): boolean;
function DoHandleError(Event: TJSErrorEvent): boolean;
@@ -856,6 +859,7 @@ type
property HotReloadPollInterval: Integer read FHotReloadPollInterval write FHotReloadPollInterval;
property HotReloadFile: string read FHotReloadFile write FHotReloadFile;
{$ENDIF}
+ property QueryString: string read FQueryString write FQueryString;
end;
function GetParentForm(AControl: TControl): TCustomForm;
@@ -1124,6 +1128,8 @@ begin
begin
hash := ClassName;
delete(hash,1,1);
+ if FQueryString <> '' then
+ hash := hash + '?' + FQueryString;
LastHash := hash;
window.location.hash := hash;
end;
@@ -2669,14 +2675,13 @@ end;
function TCustomForm.HandleHashChange(Event: TEventListenerEvent): boolean;
var
- oldURL,newURL,newHash: string;
+ oldURL,newURL,newHash,appQS: string;
pc: TPersistentClass;
newform: TForm;
+ i: Integer;
begin
- asm
- oldURL = Event.oldURL;
- newURL = Event.newURL;
- end;
+ oldURL := TJSHashChangeEvent(Event).oldURL;
+ newURL := TJSHashChangeEvent(Event).newURL;
if Assigned(OnHashChange) then
begin
@@ -2686,23 +2691,31 @@ begin
if Application.FRouting then
begin
NewHash := copy(newURL, pos('#', newURL) + 1, Length(newURL));
-
pc := GetClass('T' + Name);
if Assigned(pc) and (LastHash <> NewHash) then
begin
- if (pos('#' + Name + '_', oldURL + '_') <> 0) and
- (pos('#' + Name + '_', newURL + '_') = 0) then
+ if (pos('#' + Name + '?', oldURL + '?') <> 0) and
+ (pos('#' + Name + '?', newURL + '?') = 0) then
begin
Close;
end;
if not Popup then
begin
+ i := Pos('?', NewHash);
+ if i > 0 then
+ begin
+ appQS := Application.QueryString;
+ Application.QueryString := Copy(NewHash, i + 1, Length(NewHash));
+ SetLength(NewHash, i - 1);
+ end;
pc := GetClass('T' + NewHash);
if Assigned(pc) then
begin
Application.AutoCreateForm(TFormClass(pc), newform);
+ if i > 0 then
+ Application.QueryString := appQS;
end;
end;
end;
@@ -2955,6 +2968,19 @@ begin
DoCreate;
end;
+constructor TCustomForm.Create(id, query: string; var AReference);
+begin
+ FQueryString := query;
+ FCreating := true;
+ FFormContainer := id;
+ inherited Create(id);
+ AReference := Self;
+ FFormElement := '';
+ FModalResult := mrNone;
+ FFormStyle := fsNormal;
+ DoCreate;
+end;
+
procedure TCustomForm.CreateInitialize;
begin
inherited;
@@ -3168,6 +3194,7 @@ end;
procedure TApplication.CreateForm(AInstanceClass: TFormClass; AElementID: string; var AReference; AProc: TFormCreatedProc; LoadHTML: boolean);
var
LFileName: string;
+ LQueryString: string;
function DoStatusCreate(Event: TEventListenerEvent): boolean;
var
@@ -3199,7 +3226,7 @@ var
LElem := TJSHTMLElement(document.body);
end;
- LForm := AInstanceClass.Create(AElementID, AReference);
+ LForm := AInstanceClass.Create(AElementID, LQueryString, AReference);
LForm.FormFileName := LFileName;
if LForm.FormContainer = '' then
@@ -3251,6 +3278,7 @@ begin
end;
LFileName := AInstanceClass.GetHTMLFileName;
+ LQueryString := FQueryString;
if (LFileName <> '') and LoadHTML then
begin
FLastReq := TJSXMLHttpRequest.new;
@@ -4493,8 +4521,9 @@ end;
function TApplication.Route: boolean;
var
frm: TCustomForm;
- hash: string;
+ hash, appQS: string;
pc: TPersistentClass;
+ i: Integer;
begin
Result := false;
FRouting := true;
@@ -4502,13 +4531,21 @@ begin
if (hash <> '') then
begin
- delete(hash,1,1);
- hash := 'T' + hash;
+ hash[1] := 'T';
+ i := Pos('?', hash);
+ if i > 0 then
+ begin
+ appQS := Application.QueryString;
+ Application.QueryString := Copy(hash, i + 1, Length(hash));
+ SetLength(hash, i - 1);
+ end;
pc := GetClass(hash);
if Assigned(pc) then
begin
Result := true;
Application.AutoCreateForm(TFormClass(pc), frm);
+ if i > 0 then
+ Application.QueryString := appQS;
end;
end;
end;
To set a query string when navigating by code simply do:
Application.QueryString := 'index=12';
Application.CreateForm(TForm2, Form2);
Application.QueryString := '';
You can easily test this in the routing demo by throwing in above into the dpr or at some of the Forms codes.
This could be moved to an additional CreateForm overload as well, removing the requirement of resetting the QS but clogging the overloads further.
I'm not sure HandleHashChange should take any different action when only the query string part changed.
It will currently .Close
the active form if the form part does not match anymore
and AutoCreateForm
with the new query string. Basically the old logic.
Code like window.location.hash := '#Form2?abc=def';
works properly too as it's running through the HandleHashChange.
Not sure if I have overseen any other thing.