状态更改后 TextFormField 正在丢失值
TextFromField is losing value after sate changed
TextFromField 在状态更改时丢失其值。
这是完整的代码https://github.com/imSaharukh/cgpa_final.git
我该如何解决?
Check this GIF
问题在于您如何创建 TextEditingControllers。每次调用构建方法时,都会创建新的 TextEditingControllers。
您要做的是在 _MyHomePageState
class 的顶部创建 3 个 TextEditingController 变量。 (也不需要在飞镖中使用 new
关键字)。
class _MyHomePageState extends State<MyHomePage> {
final _formKey = GlobalKey<FormState>();
TextEditingController nameController = TextEditingController();
TextEditingController cgpaController = TextEditingController();
TextEditingController crController = TextEditingController();
并将这些传递给您的 CustomCard
child: CustomCard(
key: UniqueKey(),
index: index,
cgpa: cgpa,
namecontroller: nameController,
cgpacontroller: cgpaController,
crcontroller: crController),
希望对您有所帮助
编辑:
我不知道如何创建拉取请求,但我为您做了一些更改并在 iOS sim 上对其进行了测试。
我做了什么:
- 将详细信息重命名为课程
- 将 CusomCard 转换为有状态小部件
- 现在只有一个 Course 对象被传递给 CustomCard
- 现在可以根据课程获得钥匙。
- 将控制器移至 CustomCard
- 修改了 CGPA 中的一些代码以使其全部正常工作
class _MyHomePageState extends State<MyHomePage> {
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Stack(
children: [
Column(
children: [
Expanded(
child: Consumer<CGPA>(builder: (context, cgpa, _) {
return Form(
key: _formKey,
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: cgpa.courses.length,
itemBuilder: (BuildContext context, int index) {
return Dismissible(
key: Key(cgpa.getKeyValue(index)),
onDismissed: (direction) {
cgpa.remove(index);
print(cgpa.courses.length);
},
child: CustomCard(
course: cgpa.getCourse(index),
),
);
},
),
);
}),
),
],
),
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.all(15.0),
child: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
Provider.of<CGPA>(context, listen: false).add();
// print(cgpa.details.length);
// cgpa.details[indexs] = Details();
},
),
),
),
],
),
),
floatingActionButton: OutlineButton(
onPressed: () {
// for (var item in cgpa.details) {
// print(item.credit);
// }
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: Text("calculate"),
),
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
}
自定义卡片
class CustomCard extends StatefulWidget {
CustomCard({@required this.course});
final Course course;
@override
_CustomCardState createState() => _CustomCardState();
}
class _CustomCardState extends State<CustomCard> {
TextEditingController nameController;
TextEditingController cgpaController;
TextEditingController crController;
@override
void initState() {
super.initState();
nameController = TextEditingController(text: widget.course.name);
cgpaController = TextEditingController(
text: widget.course.gpa == null ? "" : widget.course.gpa.toString());
crController = TextEditingController(
text: widget.course.credit == null
? ""
: widget.course.credit.toString());
}
@override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
flex: 3,
child: TextFormField(
controller: nameController,
decoration: InputDecoration(labelText: "COURSE NAME"),
onChanged: (value) {
widget.course.name = value;
},
),
),
SizedBox(
width: 10,
),
Expanded(
child: TextFormField(
controller: cgpaController,
keyboardType: TextInputType.number,
decoration: InputDecoration(labelText: "GPA"),
onChanged: (value) {
//print(value);
widget.course.gpa = double.parse(value);
},
validator: (value) {
if (double.parse(value) > 4 && double.parse(value) < 0) {
return 'can\'t more then 4';
}
return null;
},
),
),
SizedBox(
width: 10,
),
Expanded(
child: TextFormField(
controller: crController,
keyboardType: TextInputType.number,
decoration: InputDecoration(labelText: "CREDIT"),
onChanged: (value) {
widget.course.credit = double.parse(value);
},
validator: (value) {
if (value.isEmpty) {
return 'can\'t be empty';
}
return null;
},
),
),
],
),
),
);
}
}
CGPA
class CGPA with ChangeNotifier {
Map<int, Course> courses = new Map();
var index = 0;
add() {
courses[index] = Course();
index++;
notifyListeners();
}
remove(int listIndex) {
courses.remove(courses.keys.toList()[listIndex]);
notifyListeners();
}
String getKeyValue(int listIndex) => courses.keys.toList()[listIndex].toString();
Course getCourse(int listIndex) => courses.values.toList()[listIndex];
}
class Course {
Course({this.credit, this.gpa, this.name});
String name;
double credit;
double gpa;
@override
String toString() {
return 'Course{name: $name, credit: $credit, gpa: $gpa}';
}
}
TextFromField 在状态更改时丢失其值。
这是完整的代码https://github.com/imSaharukh/cgpa_final.git
我该如何解决?
Check this GIF
问题在于您如何创建 TextEditingControllers。每次调用构建方法时,都会创建新的 TextEditingControllers。
您要做的是在 _MyHomePageState
class 的顶部创建 3 个 TextEditingController 变量。 (也不需要在飞镖中使用 new
关键字)。
class _MyHomePageState extends State<MyHomePage> {
final _formKey = GlobalKey<FormState>();
TextEditingController nameController = TextEditingController();
TextEditingController cgpaController = TextEditingController();
TextEditingController crController = TextEditingController();
并将这些传递给您的 CustomCard
child: CustomCard(
key: UniqueKey(),
index: index,
cgpa: cgpa,
namecontroller: nameController,
cgpacontroller: cgpaController,
crcontroller: crController),
希望对您有所帮助
编辑:
我不知道如何创建拉取请求,但我为您做了一些更改并在 iOS sim 上对其进行了测试。
我做了什么:
- 将详细信息重命名为课程
- 将 CusomCard 转换为有状态小部件
- 现在只有一个 Course 对象被传递给 CustomCard
- 现在可以根据课程获得钥匙。
- 将控制器移至 CustomCard
- 修改了 CGPA 中的一些代码以使其全部正常工作
class _MyHomePageState extends State<MyHomePage> {
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Stack(
children: [
Column(
children: [
Expanded(
child: Consumer<CGPA>(builder: (context, cgpa, _) {
return Form(
key: _formKey,
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: cgpa.courses.length,
itemBuilder: (BuildContext context, int index) {
return Dismissible(
key: Key(cgpa.getKeyValue(index)),
onDismissed: (direction) {
cgpa.remove(index);
print(cgpa.courses.length);
},
child: CustomCard(
course: cgpa.getCourse(index),
),
);
},
),
);
}),
),
],
),
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.all(15.0),
child: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
Provider.of<CGPA>(context, listen: false).add();
// print(cgpa.details.length);
// cgpa.details[indexs] = Details();
},
),
),
),
],
),
),
floatingActionButton: OutlineButton(
onPressed: () {
// for (var item in cgpa.details) {
// print(item.credit);
// }
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: Text("calculate"),
),
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
}
自定义卡片
class CustomCard extends StatefulWidget {
CustomCard({@required this.course});
final Course course;
@override
_CustomCardState createState() => _CustomCardState();
}
class _CustomCardState extends State<CustomCard> {
TextEditingController nameController;
TextEditingController cgpaController;
TextEditingController crController;
@override
void initState() {
super.initState();
nameController = TextEditingController(text: widget.course.name);
cgpaController = TextEditingController(
text: widget.course.gpa == null ? "" : widget.course.gpa.toString());
crController = TextEditingController(
text: widget.course.credit == null
? ""
: widget.course.credit.toString());
}
@override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
flex: 3,
child: TextFormField(
controller: nameController,
decoration: InputDecoration(labelText: "COURSE NAME"),
onChanged: (value) {
widget.course.name = value;
},
),
),
SizedBox(
width: 10,
),
Expanded(
child: TextFormField(
controller: cgpaController,
keyboardType: TextInputType.number,
decoration: InputDecoration(labelText: "GPA"),
onChanged: (value) {
//print(value);
widget.course.gpa = double.parse(value);
},
validator: (value) {
if (double.parse(value) > 4 && double.parse(value) < 0) {
return 'can\'t more then 4';
}
return null;
},
),
),
SizedBox(
width: 10,
),
Expanded(
child: TextFormField(
controller: crController,
keyboardType: TextInputType.number,
decoration: InputDecoration(labelText: "CREDIT"),
onChanged: (value) {
widget.course.credit = double.parse(value);
},
validator: (value) {
if (value.isEmpty) {
return 'can\'t be empty';
}
return null;
},
),
),
],
),
),
);
}
}
CGPA
class CGPA with ChangeNotifier {
Map<int, Course> courses = new Map();
var index = 0;
add() {
courses[index] = Course();
index++;
notifyListeners();
}
remove(int listIndex) {
courses.remove(courses.keys.toList()[listIndex]);
notifyListeners();
}
String getKeyValue(int listIndex) => courses.keys.toList()[listIndex].toString();
Course getCourse(int listIndex) => courses.values.toList()[listIndex];
}
class Course {
Course({this.credit, this.gpa, this.name});
String name;
double credit;
double gpa;
@override
String toString() {
return 'Course{name: $name, credit: $credit, gpa: $gpa}';
}
}