Add the Form widget and get the fields working with it. Still need to pull the values into a usable object for saving.

This commit is contained in:
Hyperling 2025-02-05 04:20:10 -07:00
parent 7ead0e5ebb
commit 99b1ec82e6

View File

@ -166,59 +166,106 @@ class ExpenseInputDialog extends StatefulWidget {
} }
class _ExpenseInputDialogState extends State<ExpenseInputDialog> { class _ExpenseInputDialogState extends State<ExpenseInputDialog> {
final _expenseFormKey = GlobalKey<FormState>();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
const inputWidth = 300.0; const inputWidth = 300.0;
const inputHeight = 50.0; const inputHeight = 50.0;
const recurrenceValues = <DropdownMenuEntry>[ const recurrenceValues = <DropdownMenuItem>[
DropdownMenuEntry(value: Recurrence.daily, label: "Daily"), DropdownMenuItem(value: Recurrence.daily, child: Text("Daily")),
DropdownMenuEntry(value: Recurrence.weekly, label: "Weekly"), DropdownMenuItem(value: Recurrence.weekly, child: Text("Weekly")),
DropdownMenuEntry(value: Recurrence.biweekly, label: "Biweekly"), DropdownMenuItem(value: Recurrence.biweekly, child: Text("Biweekly")),
DropdownMenuEntry(value: Recurrence.montly, label: "Monthly"), DropdownMenuItem(value: Recurrence.montly, child: Text("Monthly")),
DropdownMenuEntry(value: Recurrence.yearly, label: "Yearly"), DropdownMenuItem(
value: Recurrence.yearly,
child: Text(
"Yearly",
)),
]; ];
return AlertDialog( return AlertDialog(
title: Center(child: Text("Add New Expense")), title: Center(child: Text("Add New Expense")),
content: Column(mainAxisSize: MainAxisSize.min, spacing: 10, children: [ content: Form(
SizedBox( key: _expenseFormKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(mainAxisSize: MainAxisSize.min, spacing: 10, children: [
SizedBox(
width: inputWidth,
height: inputHeight,
child: TextFormField(
keyboardType: TextInputType.text,
decoration: InputDecoration(
labelText: "Name",
hintText: "Example: Red Pocket Phone Bill",
),
validator: (value) {
if (value!.isEmpty) {
return "Name must be provided.";
}
return null;
},
onChanged: (newValue) {
// _expenseFormKey.currentState!.reset();
},
)),
SizedBox(
width: inputWidth, width: inputWidth,
height: inputHeight, height: inputHeight,
child: TextField( child: TextFormField(
keyboardType: TextInputType.text, keyboardType: TextInputType.numberWithOptions(decimal: true),
decoration: InputDecoration( decoration: InputDecoration(
labelText: "Name", labelText: "Cost", hintText: "Example: 10.00"),
hintText: "Example: Red Pocket Phone Bill", validator: (value) {
), if (value!.isEmpty) {
// https://docs.flutter.dev/cookbook/forms/retrieve-input return "Cost must be provided.";
//controller: nameFieldController, }
)), if (double.tryParse(value!) == null) {
SizedBox( return "Cost must be a valid number.";
width: inputWidth, }
height: inputHeight, return null;
child: TextField( },
keyboardType: TextInputType.numberWithOptions(decimal: true), onChanged: (newValue) {
decoration: //_expenseFormKey.currentState!.reset();
InputDecoration(labelText: "Cost", hintText: "Example: 10.00"), },
),
), ),
), SizedBox(
DropdownMenu(
dropdownMenuEntries: recurrenceValues,
width: inputWidth,
label: Text("Recurrence"),
hintText: "Example: Monthly",
),
SizedBox(
width: inputWidth, width: inputWidth,
height: inputHeight, height: inputHeight,
child: TextField( child: DropdownButtonFormField(
keyboardType: TextInputType.text, items: recurrenceValues,
decoration: InputDecoration( decoration: InputDecoration(
labelText: "Description", labelText: "Recurrence", hintText: "Example: Monthly"),
hintText: "Example: 1GB data with unlimited talk & text."), validator: (value) {
)), if (value == null) {
]), return "Recurrence must be provided.";
}
return null;
},
onChanged: (newValue) {
//_expenseFormKey.currentState!.reset();
},
),
),
SizedBox(
width: inputWidth,
height: inputHeight,
child: TextFormField(
keyboardType: TextInputType.text,
decoration: InputDecoration(
labelText: "Description",
hintText: "Example: 1GB data with unlimited talk & text."),
validator: (value) {
return null;
},
onChanged: (newValue) {
//_expenseFormKey.currentState!.reset();
},
)),
]),
),
actions: [ actions: [
SizedBox( SizedBox(
width: inputWidth, width: inputWidth,
@ -238,7 +285,10 @@ class _ExpenseInputDialogState extends State<ExpenseInputDialog> {
ElevatedButton.icon( ElevatedButton.icon(
onPressed: () { onPressed: () {
print("TODO: Save expense!"); print("TODO: Save expense!");
Navigator.of(context).pop(); if (_expenseFormKey.currentState!.validate()) {
_expenseFormKey.currentState!.save();
Navigator.of(context).pop();
}
}, },
icon: Icon(Icons.save), icon: Icon(Icons.save),
label: Text('Submit'), label: Text('Submit'),