Reputation: 1354
EDIT: Tried to delete post but can't because of answer. So I am editing entire post to better describe new issue I'm having as I have now narrowed down the problem.
I have seen other posts that solve this in different situation but I cannot solve my situation with their solutions.
I have a drop down menu for quick access of frequently typed sales persons which takes in any new salesperson name and adds to the list. This is connected with my screen and I can't figure out how to not have the keyboard clear the text field on "done" tapped.
Any help is appreciated!
Screen:
class SmallAddSaleScreen extends StatefulWidget {
@override
_SmallAddSaleScreenState createState() => _SmallAddSaleScreenState();
}
class _SmallAddSaleScreenState extends State<SmallAddSaleScreen> {
final randomGen = Faker.withGenerator(random);
final uuid = Uuid();
final salesPerson = TextEditingController();
final saleAmount = TextEditingController();
final item = TextEditingController();
final dateEdited = DateTime.now().millisecondsSinceEpoch;
int saleDate = DateTime.now().millisecondsSinceEpoch;
String capitolizeFirst(String string) => string[0].toUpperCase() + string.substring(1);
@override
void initState() {
item.text = capitolizeFirst(randomGen.lorem.word());
saleAmount.text = (random.integer(13000) + random.decimal()).toStringAsFixed(2);
super.initState();
}
@override
Widget build(BuildContext context) {
String formattedDate = DateFormat.yMMMMd().format(DateTime.fromMillisecondsSinceEpoch(saleDate));
Future<void> selectSaleDate(BuildContext context) async {
final DateTime? picked = await showDatePicker(
context: context,
initialDate: DateTime.fromMillisecondsSinceEpoch(saleDate),
firstDate: DateTime(2015, 8),
lastDate: DateTime(2101),
);
if (picked != null)
setState(() {
saleDate = picked.millisecondsSinceEpoch;
});
}
return Scaffold(
body: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
children: [
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('Sales Person:'),
SizedBox(width: 20),
Container(
width: 350,
child: Consumer(builder: (context, watch, child) {
salesPerson.text = watch(appState).selectedSaleSource!;
return TextField(
controller: salesPerson,
keyboardType: TextInputType.text,
textCapitalization: TextCapitalization.words,
autocorrect: false,
decoration: InputDecoration(
border: OutlineInputBorder(borderSide: BorderSide(color: Colors.black)),
labelText: 'Name',
),
);
}),
),
]),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('Sale Amount:'),
SizedBox(width: 20),
Container(
width: 350,
child: TextField(
controller: saleAmount,
keyboardType: TextInputType.numberWithOptions(decimal: true),
textCapitalization: TextCapitalization.words,
autocorrect: false,
decoration: InputDecoration(
border: OutlineInputBorder(borderSide: BorderSide(color: Colors.black)),
labelText: '\$',
),
),
),
]),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('Item:'),
SizedBox(width: 75),
Container(
width: 350,
child: TextField(
controller: item,
keyboardType: TextInputType.text,
textCapitalization: TextCapitalization.words,
autocorrect: false,
decoration: InputDecoration(
border: OutlineInputBorder(borderSide: BorderSide(color: Colors.black)),
labelText: 'Item',
),
),
),
]),
SizedBox(height: 20),
Container(
height: 50,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('Sale date: '),
SizedBox(width: 40),
Container(
width: 350,
child: Text(formattedDate),
),
]),
),
],
),
SizedBox(width: 50),
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(height: 40),
Container(
width: 250,
child: SalesSourcePulldownMenuWidget(),
),
SizedBox(height: 100),
Container(
width: 250,
child: TextButton(
style: ButtonStyle(
textStyle: MaterialStateProperty.all(TextStyle(fontWeight: FontWeight.bold)),
foregroundColor: MaterialStateProperty.all(Colors.white),
backgroundColor: MaterialStateProperty.all(Colors.amber[800])),
onPressed: () async {
await selectSaleDate(context);
},
child: const Text('SELECT SALE DATE')),
),
SizedBox(height: 20),
Container(
width: 250,
child: TextButton(
style: ButtonStyle(
textStyle: MaterialStateProperty.all(TextStyle(fontWeight: FontWeight.bold)),
foregroundColor: MaterialStateProperty.all(Colors.white),
backgroundColor: MaterialStateProperty.all(Colors.amber[800])),
child: const Text('SAVE'),
onPressed: () async {
if (salesPerson.text.isNotEmpty && saleAmount.text.isNotEmpty && item.text.isNotEmpty) {
final userID = context.read(appState).authorizedLocalUser!.localID;
final sale = Sale(
salesPerson: salesPerson.text.trim(),
saleAmount: double.parse(saleAmount.text.trim()),
item: item.text.trim(),
saleDate: saleDate,
dateModified: dateEdited,
createdBy: userID,
saleUUID: uuid.v4(),
);
await context.read(cudServices).createSaleData(context, sale);
await context.read(appState).addSaleSource(salesPerson.text.trim());
context.read(appState).setSaleSource('');
salesPerson.text;
context.read(appState).saveSuccess(context);
} else {
context.read(appState).emptyField(context);
}
item.text = capitolizeFirst(randomGen.lorem.word()); // Randomize input
saleAmount.text =
(random.integer(13000) + random.decimal()).toStringAsFixed(2); // Randomize input
setState(() {
saleDate = DateTime.now().millisecondsSinceEpoch; // Reset input
});
},
),
)
],
)
],
),
);
}
}
Drop down widget:
class _SalesSourcePulldownMenuWidgetState extends State<SalesSourcePulldownMenuWidget> {
late String? selectedSaleSource;
bool selected = false;
@override
void initState() {
context.read(appState).getSaleSources();
super.initState();
}
@override
Widget build(BuildContext context) {
late List<String> listItems;
late List<DropdownMenuItem<String>> menuItems;
return Consumer(builder: (context, watch, child) {
listItems = watch(appState).saleSources;
selectedSaleSource = watch(appState).selectedSaleSource;
if (selectedSaleSource == '') {
selected = false;
}
menuItems = listItems
.map((String value) => DropdownMenuItem<String>(
value: value,
child: Text(value),
))
.toList();
return DropdownButton<String>(
value: selected ? selectedSaleSource : null,
isExpanded: true,
hint: const Text('Existing persons'),
items: menuItems,
onTap: () {
selected = true;
},
onChanged: (String? newValue) {
setState(() {
if (newValue != null) {
context.read(appState).setSaleSource(newValue);
selectedSaleSource = newValue;
}
});
},
);
});
}
}
Upvotes: 0
Views: 191
Reputation: 969
That's normal behavior, assign the value for those variables in initState() method:
class _SmallAddSaleScreenState extends State<SmallAddSaleScreen> {
final randomGen = Faker.withGenerator(random);
final uuid = Uuid();
final salesPerson = TextEditingController();
final saleAmount = TextEditingController();
final item = TextEditingController();
final dateEdited = DateTime.now().millisecondsSinceEpoch;
int saleDate = DateTime.now().millisecondsSinceEpoch;
String capitolizeFirst(String _s) => _s[0].toUpperCase() + _s.substring(1);
String formattedDate(DateTime _d) = DateFormat.yMMMMd().format(DateTime.fromMillisecondsSinceEpoch(_d));
@override
void initState() {
item.text = capitolizeFirst(randomGen.lorem.word());
saleAmount.text = (random.integer(13000) + random.decimal()).toStringAsFixed(2);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
...
Upvotes: 1