mysqldatabasedelphifiredacintraweb

I am trying to understand how to populate a TIWDBGrid(IntraWeb component) with a TFDStoredProc(FireDac component)


Currently I have a form that captures login data, a form with a TIWDBGrid that is supposed to return any hosts that are associated with the user_id that is created when I login from my mysql database, and a shared data module.

Below is my code for my login page

unit login_unit;

interface

uses
  Classes, SysUtils, IWAppForm, IWApplication, IWColor, IWTypes, IWCompButton,
  IWCompLabel, Vcl.Controls, IWVCLBaseControl, IWBaseControl, IWBaseHTMLControl,
  IWControl, IWCompEdit;

type
  Tlogin_form = class(TIWAppForm)
    enter_usermame_TIWEdit: TIWEdit;
    enter_password_TIWEdit: TIWEdit;
    Username: TIWLabel;
    Password: TIWLabel;
    login_TIWButton: TIWButton;
    returned_user_id_TIWEdit: TIWEdit;
    procedure login_TIWButtonClick(Sender: TObject);
  public
  end;

implementation

{$R *.dfm}

uses email_data, host_lookup_unit;


procedure Tlogin_form.login_TIWButtonClick(Sender: TObject);
var
  host_lookup_form:Thost_lookup_Form;
begin
  email_data_DataModule.Login_userProc.Prepare;
  email_data_DataModule.Login_userProc.ParamByName('user_name_').Value := enter_usermame_TIWEdit.Text;
  email_data_DataModule.Login_userProc.ParamByName('pass_word_').Value := enter_password_TIWEdit.Text;
  email_data_DataModule.Login_userProc.Execute;
  email_data_DataModule._user_id := email_data_DataModule.Login_userProc.ParamByName('user_id_').Value;
  returned_user_id_TIWEdit.Text := email_data_DataModule.Login_userProc.ParamByName('user_id_').Value;


  email_data_DataModule.Hosts_requested_frm_user_idProc.Prepare;
  email_data_DataModule.Hosts_requested_frm_user_idProc.ParamByName('user_id_').Value := email_data_DataModule._user_id;
  email_data_DataModule.Hosts_requested_frm_user_idProc.Execute;

  thost_lookup_form.Create(Self).Show;

end;

initialization
  Tlogin_form.SetAsMainForm;

end.

My host_look up page has a TIWDBGrid component and it looks like the following:

unit host_lookup_unit;

interface

uses
  Classes, SysUtils, IWAppForm, IWApplication, IWColor, IWTypes, Vcl.Controls,
  IWVCLBaseControl, IWBaseControl, IWBaseHTMLControl, IWControl, IWCompGrids,
  IWDBGrids, IWCompButton;

type
  Thost_lookup_Form = class(TIWAppForm)
    IWDBGrid1: TIWDBGrid;

  public
  end;

implementation

{$R *.dfm}

uses email_data;


end.

I made sure that the DataSource option was set to email_data_DataModule.hosts_table_requested_TDataSource

And finally the code for my data module is as follows:

unit email_data;

interface

uses
  Forms,
  SysUtils, Classes, FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Error,
  FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool,
  FireDAC.Stan.Async, FireDAC.Phys, FireDAC.Phys.MySQL, FireDAC.Phys.MySQLDef,
  FireDAC.VCLUI.Wait, FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf,
  FireDAC.DApt, Data.DB, FireDAC.Comp.DataSet, FireDAC.Comp.Client;

type
  Temail_data_DataModule = class(TDataModule)
    EmaildbConnection: TFDConnection;
    Login_userProc: TFDStoredProc;
    hosts_table_requested_TDataSource: TDataSource;
    Hosts_requested_frm_user_idProc: TFDStoredProc;
  private
  public
    _user_id : integer;
  end;

function email_data_DataModule:Temail_data_DataModule;

implementation

{$R *.dfm}

uses ServerController;
function email_data_DataModule:Temail_data_DataModule;
begin
  result := UserSession.email_data_DataModule;
end;

end.

How can I make sure to populate the data from the Hosts_requested_frm_user_idProc to my IWDBGrid?

Thanks in advance and sorry for the long post


Solution

  • There are a few issues with your application:

    First, all your forms need to have WebApplication object as the owner, so change your line where you create your IWForm to

    procedure Tlogin_form.login_TIWButtonClick(Sender: TObject);
    var
      host_lookup_form:Thost_lookup_Form;
    begin
      ...
      thost_lookup_form.Create(WebApplication).Show;
    end;
    

    Second, I think you shouldn't be using a stored proc to retrieve data, but a query object. If you are using FireDAC consider changing it to a TFDQuery which will retrieve a result set.

    Also, you must put your TDataSource in the same form where the IWDBGrid is, and connect them via IWDBGrid.DataSource property.

    Add the unit where the DataModule is declared to the uses clause of the IWForm (in the interface section), and declare a field of the form. So you should have something like this:

    unit host_lookup_unit;
    
    interface
    
    uses
      Classes, SysUtils, IWAppForm, IWApplication, IWColor, IWTypes, Vcl.Controls,
      IWVCLBaseControl, IWBaseControl, IWBaseHTMLControl, IWControl, IWCompGrids,
      IWDBGrids, IWCompButton,
      email_data;  // <- Include your DM here
    
    type
      Thost_lookup_Form = class(TIWAppForm)
        IWDBGrid1: TIWDBGrid;
        hosts_table_requested_TDataSource: TDataSource;
      private
        FDataModule: Temail_data_DataModule;
      public
      end;
    
    implementation
    
    {$R *.dfm}
    
    procedure Thost_lookup_Form .host_lookup_FormCreate(Sender: TObject);
    begin
      FDataModule := email_data_DataModule;   // set your field referencing the DM here and use it within your form. Don't use the email_data_DataModule() function anymore!
      hosts_table_requested_TDataSource.DataSet :=  FDataModule.Login_userQuery;  // Connect your DataSource and your DataSet, via code. This is the best way to do it!
    end;
    

    I also strongly suggest that you remove the logic that deals with setting parameters and opening the query from your form. This code belongs to the DataModule!

    You should have something like this:

    unit email_data;
    
    interface
    
    uses
      Forms,
      SysUtils, Classes, FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Error,
      FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool,
      FireDAC.Stan.Async, FireDAC.Phys, FireDAC.Phys.MySQL, FireDAC.Phys.MySQLDef,
      FireDAC.VCLUI.Wait, FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf,
      FireDAC.DApt, Data.DB, FireDAC.Comp.DataSet, FireDAC.Comp.Client;
    
    type
      Temail_data_DataModule = class(TDataModule)
        EmaildbConnection: TFDConnection;
        Login_userQuery: TFDQuery;
        Hosts_requested_frm_user_idQuery: TFDQuery;
      private
        F_user_id: Integer;
      public
        function SetUserNameAndPassword(const AUserName, AUserPassword: string): Integer;
      end;
    
    function email_data_DataModule:Temail_data_DataModule;
    
    implementation
    
    {$R *.dfm}
    
    uses ServerController;
    
    function email_data_DataModule: Temail_data_DataModule;
    begin
      result := UserSession.email_data_DataModule;
    end;
    
    function Temail_data_DataModule.SetUserNameAndPassword(const AUserName, AUserPassword: string): Integer;
    begin
      Login_userQuery.Prepare;
      Login_userQuery.ParamByName('user_name_').Value := AUserName;
      Login_userQuery.ParamByName('pass_word_').Value := AUserPassword;
      Login_userQuery.Open;
      F_user_id := Login_userQuery.ParamByName('user_id_').Value;
      Result := Login_userQuery.ParamByName('user_id_').Value;
    
      Hosts_requested_frm_user_idQuery.Prepare;
      Hosts_requested_frm_user_idQuery.ParamByName('user_id_').Value := F_user_id;
      Hosts_requested_frm_user_idQuery.Open;  
    end;
    
    end.
    

    all you need to do now is build and run the application. It should work.

    Note: All code above is untested (I wrote it in Notepad, not in Delphi IDE) so it might have typos and some other errors.