This expression has a type of 'void' so its value can't be used. Try checking to see if you're using the correct API; there might be a function or call that returns void you didn't expect. Also check type parameters and variables which might also be void.
The error is showing in the line number 65 exactly on the 'pop'. The code is given below.
class NewExpense extends StatefulWidget {
const NewExpense({Key? key, required this.onAddExpense}): super(
key: key,
);
final void Function(Expense expense) onAddExpense;
@override
State<StatefulWidget> createState() {
return _NewExpenseState();
}
}
class _NewExpenseState extends State<NewExpense> {
final _titleController = TextEditingController();
final _amountController = TextEditingController();
DateTime? _selectedDate;
Category _selectedCategory = Category.frameset;
void _presentDatePicker() async {
final now = DateTime.now();
final firstDate = DateTime(now.year - 1, now.month, now.day);
final pickedDate = await showDatePicker(
context: context,
initialDate: now,
firstDate: firstDate,
lastDate: now,
);
setState(() {
_selectedDate = pickedDate;
});
}
void _submitExpenseData() {
double? enterAmount = double.tryParse(_amountController.text);
final amountIsInvalid = enterAmount == null || enterAmount <= 0;
if (_titleController.text.trim().isEmpty ||
amountIsInvalid ||
_selectedDate == null) {
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: const Text('Invalid Input'),
content: const Text(
'Please make sure a valid title, amount, date and category was entered.'),
actions: [
TextButton(
onPressed: () {
Navigator.pop(ctx);
},
child: Text('Okay'),
)
],
),
);
return;
}
widget.onAddExpense(
Navigator.of(context).pop(Expense(
title: _titleController.text,
amount: enterAmount!,
date: _selectedDate!,
category: _selectedCategory)));
}
@override
void dispose() {
_titleController.dispose();
_amountController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 16),
child: Column(
children: [
TextField(
controller: _titleController,
maxLength: 50,
decoration: const InputDecoration(
label: Text('Title'),
),
),
Row(
children: [
Expanded(
child: TextField(
controller: _amountController,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
prefixText: '₹ ',
label: Text('Amount'),
),
),
),
const SizedBox(width: 16),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(_selectedDate == null
? 'No date selected'
: formatter.format(_selectedDate!)),
IconButton(
onPressed: _presentDatePicker,
icon: const Icon(
Icons.calendar_month,
),
),
],
),
),
],
),
const SizedBox(
height: 16,
),
Row(
children: [
DropdownButton(
value: _selectedCategory,
items: Category.values
.map(
(category) => DropdownMenuItem(
value: category,
child: Text(
// ignore: sdk_version_since
category.name.toUpperCase(),
),
),
)
.toList(),
onChanged: (value) {
if (value == null) {
return;
}
setState(() {
_selectedCategory = value as Category;
});
}),
const Spacer(),
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Cancel'),
),
ElevatedButton(
onPressed: _submitExpenseData,
child: const Text('Save Expense'),
),
],
),
],
),
);
}
}
I don't know which is your project flow. One thing I noticed that, you are using pop method under your onAddExpense function, which is the issue for that.
Because you can't use void method as return. You need to call pop method after your main method or return Expense() by pop the page as your goal.
#Use like this
#or