Example: Dashboard Config
A complete dashboard chart widget configuration demonstrating UnionProperty for data source selection, EnumProperty for chart type, and conditional display options.
Domain Model
| Field | Type | Description |
|---|---|---|
title | String | Widget display title |
chartType | Enum | bar / line / pie / area |
dataSource | Union | API endpoint / static data / entity query |
dateRange | Enum | last7d / last30d / last90d / custom |
customStartDate | DateTime | Start date (only when custom range) |
customEndDate | DateTime | End date (only when custom range) |
groupBy | Enum | day / week / month / quarter |
showLegend | Bool | Display legend |
showGrid | Bool | Display grid lines (bar/line/area only) |
showLabels | Bool | Display data labels |
refreshInterval | Int | Auto-refresh seconds (0 = disabled) |
Enums
dart
enum ChartType { bar, line, pie, area }
enum DateRange { last7d, last30d, last90d, custom }
enum GroupBy { day, week, month, quarter }Full Implementation
dart
import 'package:vyuh_property_system/vyuh_property_system.dart';
PropertyCollection buildDashboardChartConfig() {
final b = PropertyCollectionBuilder();
// ── General ────────────────────────────────────────────────
b.group('general', 'General');
b.string('title', 'Widget Title',
required: true,
defaultValue: 'Untitled Chart',
validators: [PropertyValidators.maxLength(100)],
);
b.enumeration<ChartType>('chartType', 'Chart Type',
options: [
EnumOption(ChartType.bar, 'Bar Chart'),
EnumOption(ChartType.line, 'Line Chart'),
EnumOption(ChartType.pie, 'Pie Chart'),
EnumOption(ChartType.area, 'Area Chart'),
],
defaultValue: ChartType.bar,
);
// ── Date Range ─────────────────────────────────────────────
b.group('dateRange', 'Date Range');
b.enumeration<DateRange>('dateRange', 'Date Range',
options: [
EnumOption(DateRange.last7d, 'Last 7 Days'),
EnumOption(DateRange.last30d, 'Last 30 Days'),
EnumOption(DateRange.last90d, 'Last 90 Days'),
EnumOption(DateRange.custom, 'Custom Range'),
],
defaultValue: DateRange.last30d,
);
b.dateTime('customStartDate', 'Start Date',
visibleCondition: PropertyCollectionBuilder.when<DateRange>(
'dateRange', DateRange.custom,
),
);
b.dateTime('customEndDate', 'End Date',
visibleCondition: PropertyCollectionBuilder.when<DateRange>(
'dateRange', DateRange.custom,
),
);
b.enumeration<GroupBy>('groupBy', 'Group By',
options: [
EnumOption(GroupBy.day, 'Day'),
EnumOption(GroupBy.week, 'Week'),
EnumOption(GroupBy.month, 'Month'),
EnumOption(GroupBy.quarter, 'Quarter'),
],
defaultValue: GroupBy.day,
);
// ── Display Options ────────────────────────────────────────
b.group('display', 'Display Options');
b.boolean('showLegend', 'Show Legend', defaultValue: true);
// Grid only makes sense for bar, line, and area charts
b.boolean('showGrid', 'Show Grid Lines',
defaultValue: true,
visibleCondition: PropertyCollectionBuilder.whenIn<ChartType>(
'chartType', {ChartType.bar, ChartType.line, ChartType.area},
),
);
b.boolean('showLabels', 'Show Data Labels', defaultValue: false);
// ── Refresh ────────────────────────────────────────────────
b.group('refresh', 'Auto-Refresh', initiallyCollapsed: true);
b.integer('refreshInterval', 'Refresh Interval (sec)',
defaultValue: 0,
help: 'Set to 0 to disable auto-refresh',
validators: [PropertyValidators.min(0), PropertyValidators.max(3600)],
);
return b.buildCollection();
}Adding Data Source with UnionProperty
The data source is best modeled as a UnionProperty because each source type has different sub-properties:
dart
PropertyCollection buildFullDashboardChartConfig() {
final collection = buildDashboardChartConfig();
final dataSource = UnionProperty(
key: 'dataSource',
label: 'Data Source',
group: 'general',
defaultSelectedKey: 'api',
options: [
UnionOption(
key: 'api',
title: 'API Endpoint',
description: 'Fetch data from a REST API',
property: StringProperty(
key: 'apiUrl',
label: 'API URL',
required: true,
validators: [PropertyValidators.pattern(
r'^https?://',
message: 'Must start with http:// or https://',
)],
help: 'Full URL including query parameters',
),
),
UnionOption(
key: 'static',
title: 'Static Data',
description: 'Use manually entered data points',
property: StringProperty(
key: 'staticJson',
label: 'JSON Data',
required: true,
help: 'Enter data as a JSON array',
),
),
UnionOption(
key: 'entityQuery',
title: 'Entity Query',
description: 'Query data from entity system',
property: StringProperty(
key: 'queryExpression',
label: 'Query Expression',
required: true,
help: 'Entity query in the format: entity.field:aggregation',
),
),
],
);
collection.addProperty(dataSource);
return collection;
}Widget Usage
dart
class ChartConfigPanel extends StatefulWidget {
final Map<String, dynamic>? savedConfig;
final ValueChanged<Map<String, dynamic>> onSave;
const ChartConfigPanel({
super.key,
this.savedConfig,
required this.onSave,
});
@override
State<ChartConfigPanel> createState() => _ChartConfigPanelState();
}
class _ChartConfigPanelState extends State<ChartConfigPanel> {
late final PropertyCollection _config;
@override
void initState() {
super.initState();
_config = buildFullDashboardChartConfig();
if (widget.savedConfig != null) {
_config.fromJson(widget.savedConfig!);
}
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(
child: PropertyCollectionEditor(
collection: _config,
showGroups: true,
disposeCollection: false,
),
),
Padding(
padding: const EdgeInsets.all(16),
child: FilledButton(
onPressed: () {
if (_config.isValid) {
widget.onSave(_config.toJson());
}
},
child: const Text('Apply Configuration'),
),
),
],
);
}
@override
void dispose() {
_config.dispose();
super.dispose();
}
}Sample JSON Output
json
{
"title": "Monthly Revenue",
"chartType": "line",
"dataSource": {
"selectedKey": "api",
"selectedValue": "https://api.example.com/revenue"
},
"dateRange": "last30d",
"groupBy": "day",
"showLegend": true,
"showGrid": true,
"showLabels": false,
"refreshInterval": 60
}With custom date range:
json
{
"title": "Enrollment Trends",
"chartType": "area",
"dataSource": {
"selectedKey": "entityQuery",
"selectedValue": "enrollment.count:sum"
},
"dateRange": "custom",
"customStartDate": "2026-01-01T00:00:00.000",
"customEndDate": "2026-03-31T23:59:59.000",
"groupBy": "week",
"showLegend": true,
"showGrid": true,
"showLabels": true,
"refreshInterval": 300
}Condition Summary
Next Steps
- Course Settings Example -- LMS course configuration
- Dynamic Behavior Guide -- Conditions and derivations
- UnionProperty Reference -- Union type details