javascripthtmldelphiproceduretms-web-core

Call procedure with parameter from HTML template in TMS WEB Core


I have a simple project in TMS WEB Core.

I want to create a series of buttons at runtime in a loop inside of my TWebHTMLDiv component and call the Delphi myFunc function based on the loop index of each button.

The myFunc function on the Delphi side takes input and sends a ShowMessage with the button index.

My problem is that I don't know how to call a function with a parameter from the template side

My unit Code:

unit Unit1;

interface

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

type
  TForm1 = class(TWebForm)
    WebHTMLDiv1: TWebHTMLDiv;
    procedure WebFormShow(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure myFunc(ACode: string);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
{ TForm1 }

procedure TForm1.myFunc(ACode: string);
begin
  ShowMessage(ACode);
end;

procedure TForm1.WebFormShow(Sender: TObject);
var
  i: integer;
begin
  WebHTMLDiv1.HTML.Text := '';
  for i := 1 to 5 do
    WebHTMLDiv1.HTML.Text := WebHTMLDiv1.HTML.Text +
      '<button type="button" onclick="myFunc(' + i.ToString +
      ')" class="btn btn-primary btn-sm">BtnNum' + i.ToString + '</button>';
end;

end.

My HTML template Code:

<html>
  <head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <title>TMS Web Project</title>
    <style>
    </style>
  </head>
  <body>
  <div id = "htmlDiv">
  </div>
  </body>
</html>

Solution

  • Method 1

    In your example, to call your Delphi myFunc procedure from JavaScript code, you can simply call the procedure like this in JavaScript:

    pas.Unit1.TForm1.myFunc('1998');
    

    And that would work. So your full WebFormShow code would be:

    procedure TForm1.WebFormShow(Sender: TObject);
    var
      i: integer;
    begin
      WebHTMLDiv1.HTML.Text := '';
      for i := 1 to 5 do
        WebHTMLDiv1.HTML.Text := WebHTMLDiv1.HTML.Text +
          '<button type="button" onclick="pas.Unit1.TForm1.myFunc(' + i.ToString +
          ')" class="btn btn-primary btn-sm">BtnNum' + i.ToString + '</button>';
    end;
    

    Method 2

    As an alternative method. You can also assign a click eventListener to each button.

    I've modified the <button> to include a data_code attribute and added a MyBtnClick class to it. I then also modified your myFunc function to have a Sender: TJSEvent parameter.

    Here's the full code:

    unit Unit1;
    
    interface
    
    uses
      System.SysUtils, System.Classes, JS, Web, WEBLib.Graphics, WEBLib.Controls,
      WEBLib.Forms, WEBLib.Dialogs, Vcl.Controls, WEBLib.WebCtrls, Vcl.StdCtrls,
      WEBLib.StdCtrls;
    
    type
      TForm1 = class(TWebForm)
        WebHTMLDiv1: TWebHTMLDiv;
        procedure WebFormShow(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
        procedure myFunc(Sender: TJSEvent);
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.dfm}
    
    procedure TForm1.myFunc(Sender: TJSEvent);
    var
      ACode: String;
    begin
      ACode := Sender.targetElement.getAttribute('data_code');
      ShowMessage(ACode);
    end;
    
    procedure TForm1.WebFormShow(Sender: TObject);
    var
      i: integer;
      MyBtnClick: TJSHTMLCollection;
    begin
      WebHTMLDiv1.HTML.Text := '';
      for i := 1 to 5 do
        WebHTMLDiv1.HTML.Text := WebHTMLDiv1.HTML.Text +
          '<button type="button" data_code="' + i.ToString +
          '" class="btn btn-primary btn-sm MyBtnClick"' +
          '>BtnNum' + i.ToString + '</button>';
    
    
      MyBtnClick := document.getElementsByClassName('MyBtnClick');
      for I := 0 to MyBtnClick.length-1 do
      begin
        MyBtnClick.Items[I].addEventListener('click', @myFunc);
      end;
    end;
    
    end.