TutWebAppServer Lesson 4 - Building tables
During this lesson, you will learn how to build a table with a variable number of rows containing dynamic data. In a typical application, a table is used to show the result of a database query (for example a list of items matching a given search criteria) or to build a list of items to fill a HTML combobox or anything else repetitive.
In this lesson, to avoid database stuff we have not yet learned, we will do something simple and yet useful: We will create a password generator. The user will be presented a form where he can enter the number of passwords he wants. The program will generated those passwords and present them in a nice HTML table.
Since we already learned how to handle HTML forms to enter data, I will quickly pass over those steps to come directly tho this lesson's objective: generate a table.
Steps
- Create the entry form to enter the number of passwords the user want to get. Save the form to c:\icstutorial\templates\GenerateTable.html. Create the code to handle the form and to get the value back. Save the code into a new unit named OverbyteIcsTutWebAppServerGenerateTable.pas. Name the two classes TUrlHandlerGenerateTable and TUrlHandlerDoGenerateTable. Map the two classes to the URL GenerateTable.html and DoGenerateTable.html. For detailed steps, please see lesson 2.
The HTML form include the following code:- <form action="DoGenerateTable.html"
- method="GET"
- enctype="application/x-www-form-urlencoded">
- Enter the number of passwords you want
- <input type="TEXT" name="PasswordCount" size="3">
- <input type="SUBMIT" value="Generate">
- </form>
- <form action="DoGenerateTable.html"
The unfinished new Delphi unit looks like:- unit OverbyteIcsTutWebAppServerGenerateTable;
- interface
- uses
- SysUtils, OverbyteIcsHttpAppServer, OverbyteIcsHttpSrv;
- type
- TUrlHandlerGenerateTable = class(TUrlHandler)
- public
- procedure Execute; override;
- end;
- TUrlHandlerDoGenerateTable = class(TUrlHandler)
- public
- procedure Execute; override;
- end;
- implementation
- procedure TUrlHandlerGenerateTable.Execute;
- begin
- AnswerPage(’’, NO_CACHE, 'GenerateTable.html', nil, []);
- Finish;
- end;
- procedure TUrlHandlerDoGenerateTable.Execute;
- var
- PasswordCount : String;
- begin
- ExtractURLEncodedValue(Params, 'PasswordCount', PasswordCount);
- // Here comes the processing and the AnswerPage
- Finish;
- end;
- end.
The two lines to be inserted in TTutWebAppServerMainForm.FormShow to map the URL are:- HttpAppSrv1.AddGetHandler('/GenerateTable.html', TUrlHandlerGenerateTable);
- HttpAppSrv1.AddGetHandler('/DoGenerateTable.html', TUrlHandlerDoGenerateTable);
- Write the code to generate the requested number of passwords. Here we have two options: either generate all passwords before generating the actual table, or generate the passwords on the fly while generating each table row. Since the first option gives a code easier to understand, I will use it. The passwords will be generated in a TStringList which will be used later when generating each table row.
Passwords will be generated using Delphi random generator. For simplicity, we will generate passwords containing uppercase and lowercase letters plus all ten digits. Passwords will have 12 characters.
The code looks like:- procedure TUrlHandlerDoGenerateTable.GeneratePasswords(PasswordCount: Integer);
- var
- Password : String;
- I : Integer;
- const
- PasswordLen = 12;
- PasswordChars : String = 'abcdefghijklmnopqrstuvwxyz' +
- 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
- '0123456789';
- begin
- RandSeed := GetTickCount;
- FPasswords := TStringList.Create;
- SetLength(Password, PasswordLen);
- while PasswordCount > 0 do begin
- for I := 1 to PasswordLen do
- Password[I] := PasswordChars[1 + Random(Length(PasswordChars))];
- FPasswords.Add(Password);
- Dec(PasswordCount);
- for I := 1 to PasswordLen do
- end;
- end;
- Now that we have a function to generate the passwords, we may use it into the simple procedure TUrlHandlerDoGenerateTable we wrote before:
- procedure TUrlHandlerDoGenerateTable.Execute;
- var
- PasswordCount : String;
- begin
- ExtractURLEncodedValue(Params, 'PasswordCount', PasswordCount);
- GeneratePasswords(StrToInt(PasswordCount));
- OnGetRowData := GetRowData;
- AnswerPage(’’, NO_CACHE, 'GeneratePasswordResult.html', nil, []);
- Finish;
- end;
- Create a new HTML template file for presenting the password list and name it GeneratePasswordResult.html. We will build a real HTML table here. There is nothing special about the HTML table except we only create one row and surround it with the special tags <#table_rows> and <#/table_rows>. When AnswerPage will find the first tag, it starts repeating the bloc until the second tag. In each iteration it call the OnGetRowData event handler to get the data and know if there are more rows.
Here is how the HTML source code looks like in the body of the HTML file:
- <table>
- <tr><td>N°</td><td>Password</td></tr>
- <#table_rows PasswordTable>
- <tr><td><#Row></td><td><#Password></td></tr>
- <#/table_rows>
- </table>
- <table>
- Write the OnGetRowData event handler with the following code:
- procedure TUrlHandlerDoGenerateTable.GetRowData(Sender: TObject;
- const TableName: String; Row: Integer; TagData: TStringIndex;
- var More: Boolean; UserData: TObject);
- begin
- More := Assigned(FPasswords) and (Row <= FPasswords.Count);
- if More then begin
- TagData.Add('Row', IntToStr(Row));
- TagData.Add('Password', FPasswords[Row - 1]);
- end;
- end;
- procedure TUrlHandlerDoGenerateTable.GetRowData(Sender: TObject;
- One more step is needed to free the stringlist holding all password. We do that in the destructor:
- destructor TUrlHandlerDoGenerateTable.Destroy;
- begin
- FreeAndNil(FPasswords);
- inherited;
- end;
- You can now hit F9 to compile and run the application. Then point your browser to http://127.0.0.1:20080/GenerateTable.html, enter a value and click the button. You you see the table built and filled with the number of passwords you requested.
Summary
In this lesson you learned how to created a template file having a table and to write code to feed the table rows with dynamic data. You know how to use <#table_rows> tag and how to write a OnGetRowData handler to fetch data for your table.
Next lesson: Relocation
Previous lesson: Simple data entry and processing
Tutorial presentation: TutWebAppServer