Here i created the some textfield and the dropdownlist when the dropdwonlist value select then i have to run setstate to update the dropdownlist value, after selecting new dropdown value the value of textfield is gone i have idea why this is happening bcoz whenever the setstate called the whole widget will rebuild so it also reset the controllers. so what is the solution about this? here is code .
import 'package:attend/constants.dart/enums.dart';
import 'package:attend/providers/user_data_provider.dart';
import 'package:attend/screens/faculty_screens/faculty_home_screen.dart';
import 'package:attend/screens/student_screens/screens/student_screen.dart';
import 'package:attend/widgets.dart/profile_image.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter/cupertino.dart';
class ProfileDetailScreen extends StatefulWidget {
static const routeName = '/profile-detail-screen';
const ProfileDetailScreen({super.key});
@override
State<ProfileDetailScreen> createState() => _ProfileDetailScreenState();
}
class _ProfileDetailScreenState extends State<ProfileDetailScreen> {
final _formKey = GlobalKey<FormState>();
var selectedGender = 'Male';
final _nameCon = TextEditingController();
final _surnameCon = TextEditingController();
final _enrollmentCon = TextEditingController();
var isValid = false;
@override
void dispose() {
_nameCon.dispose();
_surnameCon.dispose();
_enrollmentCon.dispose();
super.dispose();
}
void saveData() async {
isValid = _formKey.currentState!.validate();
if (!isValid) {
return;
}
var gender = Genders.Other;
if (selectedGender == Genders.Male.name) {
gender = Genders.Male;
} else if (selectedGender == Genders.Female.name) {
gender = Genders.Female;
}
}
@override
Widget build(BuildContext context) {
final userData = Provider.of<UserDataProvider>(context, listen: false);
//! set controller data if edit the profile
_nameCon.text = userData.name ?? '';
_surnameCon.text = userData.surname ?? '';
return Scaffold(
appBar: AppBar(
title: Text('Profile details'),
actions: [
IconButton(
onPressed: () {
saveData();
},
icon: Icon(
Icons.save,
))
],
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Form(
key: _formKey,
child: Column(
children: [
ProfileImage(selectedGender: selectedGender),
SizedBox(height: 20),
//! name textfield
TextFormField(
textCapitalization: TextCapitalization.sentences,
decoration: InputDecoration(
contentPadding:
EdgeInsets.symmetric(horizontal: 15, vertical: 10),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey),
borderRadius: BorderRadius.circular(15),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: BorderSide(
color: Colors.red,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: BorderSide(
color: Colors.grey,
),
),
filled: true,
fillColor: Colors.grey.shade100,
labelText: 'Enter your name',
labelStyle: TextStyle(color: Colors.black, fontSize: 15),
),
validator: (value) {
if (value!.isEmpty) {
return 'Please enter name!';
} else if (value.length <= 2) {
return 'Name at least 3 character long!';
}
return null;
},
controller: _nameCon,
textInputAction: TextInputAction.next,
),
SizedBox(height: 20),
//! surname textfield
TextFormField(
textCapitalization: TextCapitalization.sentences,
decoration: InputDecoration(
contentPadding:
EdgeInsets.symmetric(horizontal: 15, vertical: 10),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey),
borderRadius: BorderRadius.circular(15),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: BorderSide(
color: Colors.red,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: BorderSide(
color: Colors.grey,
),
),
filled: true,
fillColor: Colors.grey.shade100,
labelText: 'Enter your surname',
labelStyle: TextStyle(color: Colors.black, fontSize: 15),
),
validator: (value) {
if (value!.isEmpty) {
return 'Please enter surname!';
} else if (value.length <= 2) {
return 'Surname at least 3 character long!';
}
return null;
},
controller: _surnameCon,
textInputAction: userData.role == Roles.student
? TextInputAction.next
: TextInputAction.done,
),
SizedBox(height: 20),
//! if student then he has to add enrollment no
if (userData.role == Roles.student)
TextFormField(
textCapitalization: TextCapitalization.sentences,
decoration: InputDecoration(
contentPadding:
EdgeInsets.symmetric(horizontal: 15, vertical: 10),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey),
borderRadius: BorderRadius.circular(15),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: BorderSide(
color: Colors.red,
),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: BorderSide(
color: Colors.grey,
),
),
filled: true,
fillColor: Colors.grey.shade100,
labelText: 'Enter your enrollment no',
labelStyle: TextStyle(color: Colors.black, fontSize: 15),
),
validator: (value) {
if (value!.isEmpty) {
return 'Please enter enrollment no!';
} else if (value.length <= 2) {
return 'Please enter valid enrollment no!';
}
return null;
},
controller: _enrollmentCon,
textInputAction: userData.role == Roles.student
? TextInputAction.done
: TextInputAction.next,
),
SizedBox(height: 20),
//! selected gender
Row(
children: [
Text(
'Gender ',
style: TextStyle(fontSize: 17),
),
SizedBox(
width: 40,
),
DropdownButton<String>(
dropdownColor: Colors.purple.shade50,
value: selectedGender,
onChanged: (newValue) {
setState(() {
selectedGender = newValue!;
});
},
items: <String>['Male', 'Female', 'Others']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: TextStyle(
fontWeight: FontWeight.normal, fontSize: 15),
),
);
}).toList(),
),
],
),
],
),
),
),
);
}
}
I noticed that every time the _ProfileDetailScreenState
rebuilt, _nameCon
and _surnameCon
text were reset
@override
Widget build(BuildContext context) {
final userData = Provider.of<UserDataProvider>(context, listen: false);
//! set controller data if edit the profile
_nameCon.text = userData.name ?? '';
_surnameCon.text = userData.surname ?? '';
...
}
so you may need move these code into initState
or didChangeDependencies
like below
@override
void initState() {
super.initState();
final userData = Provider.of<UserDataProvider>(context, listen: false);
//! set controller data if edit the profile
_nameCon.text = userData.name ?? '';
_surnameCon.text = userData.surname ?? '';
}
or
@override
void didChangeDependencies() {
super.didChangeDependencies();
final userData = Provider.of<UserDataProvider>(context, listen: false);
//! set controller data if edit the profile
_nameCon.text = userData.name ?? '';
_surnameCon.text = userData.surname ?? '';
}