Implementation
@Preview(name: 'Advanced Filters')
Widget advancedFiltersGrid() {
final now = DateTime.now();
final data = List.generate(
100,
(index) => {
'id': index + 1,
'product': 'Product ${index + 1}',
'category': ['Electronics', 'Books', 'Clothing', 'Food', 'Toys'][index % 5],
'price': (index + 1) * 9.99,
'stock': index * 5,
'rating': 1.0 + (index % 5),
'featured': index % 3 == 0,
'created': now.subtract(Duration(days: index)),
'lastOrder': now.subtract(Duration(hours: index * 3)),
'discount': (index % 4) * 10,
'available': index % 2 == 0,
'supplier': ['Supplier A', 'Supplier B', 'Supplier C'][index % 3],
},
);
final dataSource = _LocalDataGridSource(data: data);
final controller = VooDataGridController(
dataSource: dataSource,
columns: [
const VooDataColumn<dynamic>(
field: 'product',
label: 'Product',
flex: 2,
filterWidgetType: VooFilterWidgetType.textField,
filterHint: 'Search products...',
),
const VooDataColumn<dynamic>(
field: 'category',
label: 'Category',
width: 120,
filterWidgetType: VooFilterWidgetType.dropdown,
filterOptions: [
VooFilterOption(value: 'Electronics', label: 'Electronics', icon: Icons.devices),
VooFilterOption(value: 'Books', label: 'Books', icon: Icons.book),
VooFilterOption(value: 'Clothing', label: 'Clothing', icon: Icons.checkroom),
VooFilterOption(value: 'Food', label: 'Food', icon: Icons.restaurant),
VooFilterOption(value: 'Toys', label: 'Toys', icon: Icons.toys),
],
),
VooDataColumn<dynamic>(
field: 'price',
label: 'Price',
width: 100,
filterWidgetType: VooFilterWidgetType.numberRange,
valueFormatter: (value) => '\$${value.toStringAsFixed(2)}',
filterHint: 'Min price...',
),
const VooDataColumn<dynamic>(field: 'stock', label: 'Stock', width: 80, filterWidgetType: VooFilterWidgetType.numberField, filterHint: 'Min stock...'),
VooDataColumn<dynamic>(
field: 'rating',
label: 'Rating',
width: 100,
filterWidgetType: VooFilterWidgetType.numberRange,
filterHint: 'Min rating...',
cellBuilder: (context, value, row) {
final rating = (value ?? 0.0) as double;
return Row(
children: List.generate(5, (i) {
if (i < rating.floor()) {
return const Icon(Icons.star, size: 14, color: Colors.amber);
}
return const Icon(Icons.star_border, size: 14, color: Colors.grey);
}),
);
},
),
VooDataColumn<dynamic>(
field: 'created',
label: 'Created Date',
width: 120,
filterWidgetType: VooFilterWidgetType.datePicker,
valueFormatter: (value) {
if (value is DateTime) {
return '${value.month}/${value.day}/${value.year}';
}
return '';
},
filterHint: 'Select date...',
),
VooDataColumn<dynamic>(
field: 'available',
label: 'Available',
width: 100,
filterWidgetType: VooFilterWidgetType.checkbox,
cellBuilder: (context, value, row) {
final isAvailable = value as bool? ?? false;
return Icon(isAvailable ? Icons.check_circle : Icons.cancel, color: isAvailable ? Colors.green : Colors.red, size: 20);
},
),
const VooDataColumn<dynamic>(
field: 'supplier',
label: 'Supplier',
width: 120,
filterWidgetType: VooFilterWidgetType.dropdown,
filterOptions: [
VooFilterOption(value: 'Supplier A', label: 'Supplier A'),
VooFilterOption(value: 'Supplier B', label: 'Supplier B'),
VooFilterOption(value: 'Supplier C', label: 'Supplier C'),
],
),
],
showFilters: true,
);
dataSource.loadData();
return Material(
child: SizedBox(height: 600, child: VooDataGrid(controller: controller)),
);
}