I'm still new in Flutter, I'm trying to Update Text() based on user input in a TextFormField() within a form, perform two calculations and display results in other TextFormField() then POST the data to an API on pressing the Upload Button. I have tried using setState(){} as below but it's not working out. 'serviceFee' is supposed to be 2% of the 'amount' entered by the user then 'takeHome' is supposed to be 'amount' minus 'serviceFee'. Below is my code...
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:keilvog/Screens/6kg_cylinder_screen.dart';
import 'package:keilvog/Widget/edit_image.dart';
import 'package:keilvog/Widget/header.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:http/http.dart' as http;
import 'package:keilvog/Widget/validators.dart';
import 'package:shared_preferences/shared_preferences.dart';
class SellDetails extends StatefulWidget {
const SellDetails({Key? key}) : super(key: key);
@override
State<SellDetails> createState() => _SellDetailsState();
}
class _SellDetailsState extends State<SellDetails> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final brandController = TextEditingController();
final capacityController = TextEditingController();
final amountController = TextEditingController();
final serviceFeeController = TextEditingController();
final takeHomeController = TextEditingController();
File? image;
bool isLoading = false;
double _serviceFee = 0;
// ignore: unused_field
double _takeHome = 0;
double amount = 0;
Future UploadData({
String? brand,
String? capacity,
double? amount,
double? serviceFee,
double? takeHome,
File? image
}) async
{
final SharedPreferences preferences = await SharedPreferences.getInstance();
final String? myJWT = preferences.getString('jwt');
Map<String, dynamic> token = jsonDecode(myJWT!);
final myResponse = await http.post(
Uri.parse('https://kelivog.com/sell/cylinder'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
'X-Requested-With': 'XMLHttpRequest',
'Authorization': '$token',
},
body: jsonEncode(
{
'brand': brand,
'capacity': capacity,
'amount': amount,
'serviceFee': serviceFee,
'takeHome': takeHome,
'image':'data:image/png;base64,' base64Encode(image!.readAsBytesSync()),
}),
);
return myResponse.statusCode;
}
@override
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage("images/background.jpg"), fit: BoxFit.cover)),
child: Scaffold(
// body: SingleChildScrollView(
body: SingleChildScrollView(
child: Column(
children: [
header(),
SizedBox(height: 20.h),
const EditImage(),
SizedBox(height: 30.h),
Container(
width: 350.w,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(15.r)),
image: const DecorationImage(
image: AssetImage("images/background.jpg"),
fit: BoxFit.fitWidth,
alignment: Alignment.topCenter,
),
boxShadow: const [
BoxShadow(color: Colors.grey, spreadRadius: 2),
],
),
child: Column(
children: [
Padding(
padding: EdgeInsets.symmetric(
vertical: 12.h, horizontal: 16.w),
child: Row(
children: [
Expanded(
child: Text("BRAND",
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.bold,
)),
),
SizedBox(width: 1.w),
Expanded(
child: Container(
width: 90.w,
height: 40.h,
decoration: BoxDecoration(
color: Colors.yellow[600],
borderRadius: BorderRadius.circular(15)),
child: Center(
child: TextFormField(
//textAlignVertical: TextAlignVertical.center,
validator: brandValidator,
controller: brandController,
showCursor: false,
style: const TextStyle(
fontSize: 20.0,
height: 2.0,
color: Colors.black,
),
decoration: const InputDecoration(
contentPadding: EdgeInsets.only(
top: 1.0, bottom: 100.0, left: 8.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(15.0)),
),
),
),
),
),
),
],
),
),
//const Divider(indent: 15, endIndent: 15, thickness: 2),
Padding(
padding: EdgeInsets.symmetric(
vertical: 12.h, horizontal: 16.w),
child: Row(
children: [
Expanded(
child: Text("CAPACITY",
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.bold,
)),
),
SizedBox(width: 1.w),
Expanded(
child: Container(
width: 90.w,
height: 40.h,
decoration: BoxDecoration(
color: Colors.yellow[600],
borderRadius: BorderRadius.circular(15)),
child: Center(
child: TextFormField(
validator: capacityValidator,
controller: capacityController,
showCursor: false,
style: const TextStyle(
fontSize: 20.0,
height: 2.0,
color: Colors.black,
),
decoration: const InputDecoration(
contentPadding: EdgeInsets.only(
top: 1.0, bottom: 100.0, left: 8.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(15.0)),
),
),
),
),
),
),
],
),
),
Padding(
padding: EdgeInsets.symmetric(
vertical: 12.h, horizontal: 16.w),
child: Row(
children: [
Expanded(
child: Text("AMOUNT",
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.bold,
)),
),
SizedBox(width: 1.w),
Expanded(
child: Container(
width: 90.w,
height: 40.h,
decoration: BoxDecoration(
color: Colors.yellow[600],
borderRadius: BorderRadius.circular(15)),
child: Center(
child: TextFormField(
validator: amountValidator,
controller: amountController,
keyboardType: TextInputType.number,
showCursor: false,
style: const TextStyle(
fontSize: 20.0,
height: 2.0,
color: Colors.black,
),
decoration: const InputDecoration(
contentPadding: EdgeInsets.only(
top: 1.0, bottom: 100.0, left: 8.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(15.0)),
),
),
onChanged: (value) {
setState(() {
amount = value as double;
});
},
),
),
),
),
],
),
),
Padding(
padding: EdgeInsets.symmetric(
vertical: 12.h, horizontal: 16.w),
child: Row(
children: [
Expanded(
child: Text("SERVICE FEE",
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.bold,
)),
),
SizedBox(width: 1.w),
Expanded(
child: Container(
width: 90.w,
height: 40.h,
decoration: BoxDecoration(
color: Colors.yellow[600],
borderRadius: BorderRadius.circular(15)),
child: Center(
//child: Text(serviceFeeController.text),
child: TextFormField(
onChanged: (value) => setState(() {
_serviceFee = value as double;
}),
// validator: ,
// controller: ,
showCursor: false,
style: const TextStyle(
fontSize: 20.0,
height: 2.0,
color: Colors.black,
),
decoration: const InputDecoration(
contentPadding: EdgeInsets.only(
top: 1.0, bottom: 100.0, left: 8.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(15.0)),
),
),
),
),
),
),
],
),
),
Padding(
padding: EdgeInsets.symmetric(
vertical: 12.h, horizontal: 16.w),
child: Row(
children: [
Expanded(
child: Text("TAKE HOME",
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.bold,
)),
),
SizedBox(width: 1.w),
Expanded(
child: Container(
width: 90.w,
height: 40.h,
decoration: BoxDecoration(
color: Colors.yellow[600],
borderRadius: BorderRadius.circular(15)),
child: Center(
//child: Text(serviceFeeController.text),
child: TextFormField(
onChanged: (value) => setState(() {
_takeHome = value as double;
}),
// validator: ,
// controller: ,
showCursor: false,
style: const TextStyle(
fontSize: 20.0,
height: 2.0,
color: Colors.black,
),
decoration: const InputDecoration(
contentPadding: EdgeInsets.only(
top: 1.0, bottom: 100.0, left: 8.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(15.0)),
),
),
),
),
),
),
],
),
),
// rowItem('BRAND'),
// rowItem('CAPACITY'),
// rowItem('AMOUNT'),
// rowItem('SERVICE FEE'),
// rowItem('TAKE HOME'),
],
),
),
SizedBox(height: 40.h),
ElevatedButton(
onPressed: () async {
setState(() {
_serviceFee = (amount * 0.02);
});
setState(() {
_takeHome = amount - _serviceFee;
});
//final FormState? form = _formKey.currentState;
if (_formKey.currentState!.validate()){
if (image != null) {
await UploadData(
image: image,
brand: brandController.text,
capacity: capacityController.text,
amount: amountController.text as double,
serviceFee: serviceFeeController.text as double,
takeHome: takeHomeController.text as double
);
}
else
{
// ignore: avoid_print
print('You have not added an image');
}
if (isLoading) {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) =>
const SixCylindersListsScreen(
item: '', id: '', title: '',
)));
} else {
throw Exception('Failed to upload details.');
}
}
},
child: Text(
'UPLOAD',
style: TextStyle(
color: Colors.yellow[600],
fontSize: 22.sp,
fontWeight: FontWeight.w700,
),
),
style: ElevatedButton.styleFrom(
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.r),
),
fixedSize: Size(150.w, 50.h),
primary: const Color(0xff261005),
),
),
],
),
),
),
);
}
}
CodePudding user response:
use double.parse(value) to be able to assign value to the double declared values
CodePudding user response:
Here a quick example
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp>{
final TextEditingController _controller = TextEditingController();
double? fees;
double? takeHome;
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Column(
children: [
TextFormField(
decoration: const InputDecoration(
labelText: 'Type the amount',
),
controller: _controller,
),
const SizedBox(height: 20),
OutlinedButton(
child:const Text('OK'),
onPressed: () => _doTheMath(),
),
const SizedBox(height: 20),
if(fees != null)
Text('fee: $fees'),
const SizedBox(height: 20),
if(takeHome != null)
Text('takeHome: $takeHome'),
]),
),
);
}
_doTheMath(){
//perform validation then do the math
double? amount = double.tryParse(_controller.text);
if(amount != null) {
setState((){
final serviceFee = amount * 0.02;
fees = serviceFee;
takeHome = amount - serviceFee;
});
} else {
print('Invalid input');
setState((){
fees = null;
takeHome = null;
});
}
}
}