Editing Tasks
Your sample application now works pretty well as a read-only application, but it's time to start adding some features to add and change data. You are going to start by adding the ability to edit existing tasks.
Edit Task Form
Add a new form to the project and name it EditForm.
Add the following controls:
TEdit
, name: editTitleTDateTimePicker
, name: dateDueDateTComboBox
, name: comboPriorityTMemo
, name: editDescriptionTCheckBox
, name: checkIsCompletedTButton
, name: btnOK withModalResult
set to OKTButton
, name: ***btnCancel withModalResult
set to Cancel
Add labels and place controls as shown in the screenshot:
Clone The Properties Table
Create a new TDAMemDataTable
instance (found in the RemObjects Data Abstract section of the Tool Palette) in the ClientDataModule and set it up with the following properties:
- Name: tbl_cloneProperties
- CloneSource: tbl_Priorities
- CloneAutoOpen: true
This table clones the tbl_Priorities table, so the cloned table can be looped without changing position in tbl_Priorities.
Edit Form Code
Back in fEditForm.pas
, implement the event for btnOnClick
and FormShow
.
//fEditForm.pas
unit fEditForm;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls, DB;
type
TEditForm = class(TForm)
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
editTitle: TEdit;
dateDueDate: TDateTimePicker;
comboPriority: TComboBox;
editDescription: TMemo;
checkIsCompleted: TCheckBox;
btnOK: TButton;
btnCancel: TButton;
procedure FormShow(Sender: TObject);
procedure btnOKClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
EditForm: TEditForm;
implementation
{$R *.dfm}
uses
fClientDataModule, uDAMemDataTable;
procedure TEditForm.btnOKClick(Sender: TObject);
var
l_tbl_tasks : TDAMemDataTable;
begin
l_tbl_tasks := ClientDataModule.tbl_Tasks;
l_tbl_tasks.FieldByName('Task').AsWideString := editTitle.Text;
l_tbl_tasks.FieldByName('DueDate').AsDateTime := dateDueDate.Date;
l_tbl_tasks.FieldByName('Priority').AsLargeInt := Integer(comboPriority.Items.Objects[comboPriority.ItemIndex]);
l_tbl_tasks.FieldByName('Details').AsWideString := editDescription.Text;
if checkIsCompleted.Checked then
l_tbl_tasks.FieldByName('Done').AsLargeInt := 1
else
l_tbl_tasks.FieldByName('Done').AsLargeInt := 0;
end;
procedure TEditForm.FormShow(Sender: TObject);
var
l_tbl_tasks, l_tbl_priority: TDAMemDataTable;
i: integer;
begin
//set up comboPriority
comboPriority.Items.Clear;
l_tbl_priority := ClientDataModule.tbl_clonePriorities;
l_tbl_priority.Open;
l_tbl_priority.First;
while not l_tbl_priority.EOF do begin
comboPriority.Items.AddObject(
l_tbl_priority.FieldByName('Name').AsWideString,
Pointer(l_tbl_priority.FieldByName('Id').AsLargeInt));
l_tbl_priority.Next;
end;
//reference the tasks table
l_tbl_tasks := ClientDataModule.tbl_Tasks;
//if the tasks table is in edit mode, get the details from
//the current record and set up the edit controls
if l_tbl_tasks.State = dsEdit then begin
editTitle.Text := l_tbl_tasks.FieldByName('Task').AsWideString;
dateDueDate.Date := l_tbl_tasks.FieldByName('DueDate').AsDateTime;
for i := 0 to comboPriority.Items.Count-1 do
if Integer(comboPriority.Items.Objects[i]) = l_tbl_tasks.FieldByName('Priority').AsLargeInt then begin
comboPriority.ItemIndex := i;
Break;
end;
editDescription.Text := l_tbl_tasks.FieldByName('Details').AsWideString;
checkIsCompleted.Checked := l_tbl_tasks.FieldByName('Done').AsLargeInt = 1;
end
else begin
//no record to edit yet, so initialize the date and priority
dateDueDate.Date := Date;
comboPriority.ItemIndex := 0;
end;
end;
end.
Spend a few moments looking at the code. It is hopefully pretty straightforward. The FormShow
event checks whether tbl_tasks is in an edit state and whether it populates the controls with the current values.
If tbl_tasks is not in an edit state, the controls are simply initialized. When btnOK is clicked, the values are simply copied from the controls into the current record of tbl_tasks
The DataModule
Add Forms, UITypes and fEditForm units into the uses section of the fClientDataModule:
uses
Forms, UITypes,
fLogOnForm, fEditForm;
Add a public method, editTask
, to the DataModule. This method checks whether tbl_tasks is on a valid record.
If it is, put tbl_tasks into edit mode and create an instance of EditForm
.
When the EditForm
closes, either Post the changes to tbl_tasks or cancel them.
procedure TClientDataModule.EditTask;
var
leditform: TEditForm;
begin
if tbl_Tasks.BOF and tbl_Tasks.EOF then begin
Exit;
end;
leditform := TEditForm.Create(Application);
try
leditform.Caption := 'Edit Task';
tbl_Tasks.Edit;
if leditform.ShowModal = mrOk then
tbl_Tasks.Post
else
tbl_Tasks.Cancel;
finally
leditform.Release;
end;
end;
The ClientForm
Add another TButton
to the main form, call it btnEdit and set its caption to Edit.
In btnEdit's onClick
, call the editTask
method of the DataModule.
procedure TClientForm.btnEditClick(Sender: TObject);
begin
ClientDataModule.editTask();
end;
With that done, your sample app should now be able to edit tasks.