Database adapter
TTMSFNCPlannerDatabaseAdapter connects a planner to any TDataSet through a
TDataSource, so appointments are loaded from and saved to a database instead of
created in code. You map each planner item field to a dataset field once, activate
the adapter, and the planner reads, inserts, updates, and deletes items as the
user interacts with it. Reach for the adapter whenever the schedule must persist
between sessions or be shared across machines. This guide covers field mapping,
activation, reloading on navigation, and the customization events.
Field mapping
The adapter's Item sub-object holds one string property per planner field; set
each to the name of the dataset field that supplies it. AutoIncrementDBKey
lets the adapter generate keys for new rows:
procedure TForm1.BindPlannerToDataset;
begin
// Map each planner item field to a dataset field name.
PlannerDatabaseAdapter1.Item.DataSource := DataSource1;
PlannerDatabaseAdapter1.Item.DBKey := 'Id';
PlannerDatabaseAdapter1.Item.StartTime := 'StartTime';
PlannerDatabaseAdapter1.Item.EndTime := 'EndTime';
PlannerDatabaseAdapter1.Item.Title := 'Title';
PlannerDatabaseAdapter1.Item.Text := 'Notes';
PlannerDatabaseAdapter1.Item.Resource := 'Resource';
PlannerDatabaseAdapter1.Item.Recurrency := 'Recurrency';
PlannerDatabaseAdapter1.Item.AutoIncrementDBKey := True;
// Connect the adapter to the planner and activate it.
Planner1.Adapter := PlannerDatabaseAdapter1;
PlannerDatabaseAdapter1.Active := True;
// Reload the visible window whenever the user navigates.
Planner1.OnAfterNavigateToDateTime := PlannerAfterNavigate;
end;
procedure TForm1.PlannerAfterNavigate(Sender: TObject;
ADirection: TTMSFNCPlannerNavigationDirection;
ACurrentDateTime: TDateTime; ANewDateTime: TDateTime);
begin
PlannerDatabaseAdapter1.GetItems(Planner1.TimeLine.ViewStart,
Planner1.TimeLine.ViewStart + 7);
end;
Assign the adapter to Planner1.Adapter and set Adapter.Active := True to load
the data. The Recurrency mapping is optional — map it only when the dataset
stores RRULE strings.
Loading a time window
GetItems(PeriodFrom, PeriodTo) loads the items for a date range; LoadItems
reloads everything. Because a planner only shows one window at a time, reload on
the OnAfterNavigateToDateTime event (wired in the snippet above) so moving to
the next week fetches that week's rows. OnItemsLoaded fires after a load
completes — use it to update a status indicator:
procedure TForm1.LoadVisibleWindow;
begin
// Load only the items in the current view (here a seven-day window).
PlannerDatabaseAdapter1.GetItems(Planner1.TimeLine.ViewStart,
Planner1.TimeLine.ViewStart + 7);
end;
procedure TForm1.ReloadEverything;
begin
PlannerDatabaseAdapter1.LoadItems;
end;
procedure TForm1.PlannerItemsLoaded(Sender: TObject);
begin
// OnItemsLoaded fires after a load completes.
Caption := Format('%d appointments loaded', [Planner1.Items.Count]);
end;
Customizing reads and writes
Two events let you translate between item and dataset when the default field mapping is not enough:
OnFieldsToItem— populate aTTMSFNCPlannerItemfrom the current dataset row (e.g. deriveColorfrom a status field).OnItemToFields— write aTTMSFNCPlannerItemback into dataset fields before post (e.g. split a combined field).
OnItemInserted, OnItemUpdated, and OnItemRead report each persisted change,
and OnItemCreateDBKey supplies a custom key when AutoIncrementDBKey is off.
Putting it together
This example combines field mapping with a read customization: items are colored
from a Status column as each row is read into the planner, so the data binding
and the appearance are driven entirely by the dataset:
procedure TForm1.BindWithStatusColors;
begin
// Standard field mapping.
PlannerDatabaseAdapter1.Item.DataSource := DataSource1;
PlannerDatabaseAdapter1.Item.DBKey := 'Id';
PlannerDatabaseAdapter1.Item.StartTime := 'StartTime';
PlannerDatabaseAdapter1.Item.EndTime := 'EndTime';
PlannerDatabaseAdapter1.Item.Title := 'Title';
// Customize each read: color the item from a status column.
PlannerDatabaseAdapter1.OnFieldsToItem := AdapterFieldsToItem;
Planner1.Adapter := PlannerDatabaseAdapter1;
PlannerDatabaseAdapter1.Active := True;
end;
procedure TForm1.AdapterFieldsToItem(Sender: TObject; AFields: TFields;
AItem: TTMSFNCPlannerItem);
begin
if AFields.FindField('Status') <> nil then
begin
if AFields.FieldByName('Status').AsString = 'Urgent' then
AItem.Color := gcRed
else
AItem.Color := gcCornflowerblue;
AItem.FontColor := gcWhite;
end;
end;
Pitfalls
- Map
DBKeyfor updates and deletes. Without aDBKeymapping the adapter cannot locate the row behind an item, so edits and deletes will not persist. - Activate after mapping. Set the field names first, then
Adapter.Active := True; activating against an unmapped adapter loads nothing. - Reload on navigation. The adapter loads the current window; if you do not
call
GetItemsfromOnAfterNavigateToDateTime, navigating shows an empty period. AutoIncrementDBKeyvs. database keys. Turn it off and handleOnItemCreateDBKeywhen the database (not the adapter) assigns primary keys.
Related API
TTMSFNCPlannerDatabaseAdapter—Item,Active,GetItems,LoadItems,OnFieldsToItem,OnItemToFields,OnItemsLoadedTTMSFNCPlanner—Adapter,OnAfterNavigateToDateTime,FindItemWithDBKey
See also
- Items — the item fields the adapter maps
- Recurrence — persisting recurring items via the RRULE field
- Timeline — the navigation that drives reloads