Flutter flatter从另一个小部件保存多个表单数据
我试图用列表视图生成器显示颤振表单列表。我已经完成的UI 我现在想访问每个表单的数据并进行验证,有人可以指导我吗 我尝试了不同的方法并检查了StackOverflow上类似的帖子,但没有找到任何解决方案 条目\u widget.dart-创建表单的位置Flutter flatter从另一个小部件保存多个表单数据,flutter,dart,Flutter,Dart,我试图用列表视图生成器显示颤振表单列表。我已经完成的UI 我现在想访问每个表单的数据并进行验证,有人可以指导我吗 我尝试了不同的方法并检查了StackOverflow上类似的帖子,但没有找到任何解决方案 条目\u widget.dart-创建表单的位置 class EntriesWidget extends StatefulWidget { EntriesWidget({Key key}) : super(key: key); @override EntriesWidgetStat
class EntriesWidget extends StatefulWidget {
EntriesWidget({Key key}) : super(key: key);
@override
EntriesWidgetState createState() => EntriesWidgetState();
}
class EntriesWidgetState extends State<EntriesWidget> {
List<EntryCard> entryCardList = [];
int count = 0;
void removeEntryCard(index) {
print("inside remove function ${index}");
setState(() {
entryCardList.remove(index);
// index++;
});
}
void addEntryCard() {
setState(() {
entryCardList.add(
EntryCard(removeEntryCard, index: entryCardList.length),
);
});
}
@override
void initState() {
// addEntryCard(); //Initialize with 1 item
super.initState();
}
@override
Widget build(BuildContext context) {
return Material(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('1. HRD Timesheet (Systems)', style: kDefaultTitleStyle),
GestureDetector(
onTap: addEntryCard,
child: Chip(
label: Text('+ Add Task'),
backgroundColor: Colors.grey,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
),
],
),
SizedBox(height: 10.0),
Container(
decoration: BoxDecoration(
border: Border.all(color: kPrimaryAppColor),
),
child: Padding(
padding: const EdgeInsets.all(6.0),
child: Column(
children: [
ListView(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
children: [
...entryCardList,
],
),
],
),
),
),
],
),
);
}
void saveForm2() {
print("inside save form");
// if (formKey.currentState.validate()) {
// formKey.currentState.save();
// print(widget.taskEntry.taskName);
// print(widget.taskEntry.taskHours);
// }
}
}
class EntryCard extends StatefulWidget {
final TaskEntry taskEntry;
final int index;
final Function(EntryCard) removeEntryCard;
// final TextEditingController hours;
// final TextEditingController task;
const EntryCard(this.removeEntryCard,
{Key key, @required this.index, this.taskEntry})
: super(key: key);
void remove() {
print("Called remove on " + this.hashCode.toString());
removeEntryCard(this);
}
@override
EntryCardState createState() {
return EntryCardState(index, remove);
}
}
class EntryCardState extends State<EntryCard> {
final int entryIndex;
final Function() remove;
final formKey = GlobalKey<FormState>();
EntryCardState(this.entryIndex, this.remove);
@override
Widget build(BuildContext context) {
return Form(
key: formKey,
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: TextFormField(
// initialValue: widget.user.fullName,
onSaved: (val) => widget.taskEntry.taskHours = val,
validator: (val) => val.length > 1 ? null : 'Invalid Field',
// controller: widget.hours,
decoration: InputDecoration(
hintText: "Hours ${widget.index}",
isDense: true,
// border: OutlineInputBorder(),
),
),
),
SizedBox(width: 5.0),
Expanded(
child: TextFormField(
onSaved: (val) => widget.taskEntry.taskName = val,
validator: (val) => val.length > 1 ? null : 'Invalid Field',
// controller: widget.task,
decoration: InputDecoration(
hintText: "Task Name ${widget.index}",
// border: OutlineInputBorder(),
isDense: true,
),
),
),
IconButton(
icon: Icon(Icons.remove),
color: kPrimaryAppColor,
onPressed: () {
widget.remove();
},
)
],
),
SizedBox(height: 5.0),
// TextFormField(
// decoration: InputDecoration(
// hintText: "This is Remarks ${index}",
// border: O`utlineInputBorder(),
// ),
// ),
// SizedBox(height: 10.0),
],
),
);
}
void saveForm() {
print("inside save form");
if (formKey.currentState.validate()) {
formKey.currentState.save();
print(widget.taskEntry.taskName);
print(widget.taskEntry.taskHours);
}
}
}
您可以复制粘贴运行下面的完整代码
描述所有细节太长了,您可以直接参考下面的完整代码和工作演示
步骤1:对于
EntriesWidget(key:key[index]),您需要List
代码>
List<GlobalKey<EntriesWidgetState>> key = [
GlobalKey<EntriesWidgetState>(),
GlobalKey<EntriesWidgetState>()
];
...
Flexible(
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: 2,
itemBuilder: (context, index) {
return EntriesWidget(key: key[index]);
},
),
),
submitData() {
print("inside submit");
key.forEach((element) {
element.currentState.saveForm2();
});
}
...
void saveForm2() {
keyForm.forEach((element) {
element.currentState.saveForm();
});
步骤3:为循环每个键
并调用saveForm
List<GlobalKey<EntriesWidgetState>> key = [
GlobalKey<EntriesWidgetState>(),
GlobalKey<EntriesWidgetState>()
];
...
Flexible(
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: 2,
itemBuilder: (context, index) {
return EntriesWidget(key: key[index]);
},
),
),
submitData() {
print("inside submit");
key.forEach((element) {
element.currentState.saveForm2();
});
}
...
void saveForm2() {
keyForm.forEach((element) {
element.currentState.saveForm();
});
工作演示
完整代码
import 'package:flutter/material.dart';
const Color kPrimaryAppColor = Colors.blue;
TextStyle kDefaultTitleStyle = TextStyle(color: Colors.black);
TextStyle kDefaultParagraphStyle = TextStyle(color: Colors.black);
class TaskEntry {
String taskName;
String taskHours;
TaskEntry({this.taskName = '', this.taskHours = ''});
String toString() {
return 'Student: {TaskName: $taskName, TaskHours: $taskHours}';
}
}
List<GlobalKey<EntriesWidgetState>> key = [
GlobalKey<EntriesWidgetState>(),
GlobalKey<EntriesWidgetState>()
];
//final keyForm = GlobalKey<EntryCardState>();
class AddTimesheet extends StatefulWidget {
@override
_AddTimesheetState createState() => _AddTimesheetState();
}
class _AddTimesheetState extends State<AddTimesheet> {
String dropdownValue = 'Week 1';
// List<TaskEntry> taskEntries = [];
List<EntriesWidget> entriesWidgets = [];
// var cards = <Card>[];
submitData() {
print("inside submit");
key.forEach((element) {
element.currentState.saveForm2();
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: SingleChildScrollView(
physics: ScrollPhysics(),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Text(
'Naman Ambavi - 1405',
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 20.0,
color: kPrimaryAppColor,
),
),
),
SizedBox(height: 15.0),
Text('Week', style: kDefaultTitleStyle),
Container(
width: 300,
child: DropdownButton(
isExpanded: true,
value: dropdownValue,
icon: Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: TextStyle(color: kPrimaryAppColor),
underline: Container(
height: 2,
color: kPrimaryAppColor,
),
onChanged: (String newValue) {
setState(() {
dropdownValue = newValue;
});
},
items: <String>[
'Week 1',
'Week 2 (1st Oct - 10th Oct)',
'Week 3'
].map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
),
SizedBox(
height: 18.0,
),
const Divider(
color: kPrimaryAppColor,
thickness: 0.5,
),
Text('Select Department', style: kDefaultTitleStyle),
SizedBox(height: 20.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
FlatButton(
color: kPrimaryAppColor,
textColor: Colors.white,
disabledColor: Colors.grey,
disabledTextColor: Colors.black,
padding: EdgeInsets.all(8.0),
splashColor: kPrimaryAppColor,
onPressed: () {
/*...*/
},
child: Text(
"IT",
style: TextStyle(fontSize: 20.0),
),
),
FlatButton(
color: kPrimaryAppColor,
textColor: Colors.white,
disabledColor: Colors.grey,
disabledTextColor: Colors.black,
padding: EdgeInsets.all(8.0),
splashColor: kPrimaryAppColor,
onPressed: () {
/*...*/
},
child: Text(
"PMT",
style: TextStyle(fontSize: 20.0),
),
),
FlatButton(
color: kPrimaryAppColor,
textColor: Colors.white,
disabledColor: Colors.grey,
disabledTextColor: Colors.black,
padding: EdgeInsets.all(8.0),
splashColor: kPrimaryAppColor,
onPressed: () {
/*...*/
},
child: Text(
"AV",
style: TextStyle(fontSize: 20.0),
),
),
],
),
SizedBox(height: 15.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'IT Hours for week: 35/40 hours',
style: kDefaultParagraphStyle,
),
Chip(
label: Text('View Log'),
backgroundColor: Colors.grey,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
],
),
SizedBox(height: 20.0),
// Expanded(
// child: ListView.builder(
// itemCount: cards.length,
// itemBuilder: (BuildContext context, int index) {
// return cards[index];
// },
// ),
// ),
SizedBox(height: 20.0),
// EntriesWidget(),
Flexible(
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: 2,
itemBuilder: (context, index) {
return EntriesWidget(key: key[index]);
},
),
),
SizedBox(height: 20.0),
Center(
child: FlatButton(
color: kPrimaryAppColor,
textColor: Colors.white,
disabledColor: Colors.grey,
disabledTextColor: Colors.black,
padding: EdgeInsets.all(8.0),
splashColor: kPrimaryAppColor,
onPressed: submitData,
child: Text(
"Add Log",
style: TextStyle(fontSize: 20.0),
),
),
),
],
),
),
),
);
}
void onSave() {
// entries.forEach((form) => allValid = allValid && form.isValid());
// var data = taskEntries.map((it) => it.taskEntries).toList();
}
}
class EntriesWidget extends StatefulWidget {
EntriesWidget({Key key}) : super(key: key);
@override
EntriesWidgetState createState() => EntriesWidgetState();
}
class EntriesWidgetState extends State<EntriesWidget> {
List<EntryCard> entryCardList = [];
int count = 0;
List<GlobalKey<EntryCardState>> keyForm = [];
int keyFormIndex = -1;
void removeEntryCard(index, EntryCard) {
print("inside remove function ${index}");
keyFormIndex = keyFormIndex - 1;
var pos = entryCardList.indexOf(EntryCard);
print("pos $pos");
setState(() {
entryCardList.removeAt(pos);
keyForm.removeAt(pos);
// index++;
});
}
void addEntryCard() {
setState(() {
keyForm.add(GlobalKey<EntryCardState>());
keyFormIndex = keyFormIndex + 1;
entryCardList.add(
EntryCard(
removeEntryCard,
key: keyForm[keyFormIndex],
index: entryCardList.length,
taskEntry: TaskEntry(),
),
);
});
}
@override
void initState() {
// addEntryCard(); //Initialize with 1 item
super.initState();
}
@override
Widget build(BuildContext context) {
return Material(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('1. HRD Timesheet (Systems)', style: kDefaultTitleStyle),
GestureDetector(
onTap: addEntryCard,
child: Chip(
label: Text('+ Add Task'),
backgroundColor: Colors.grey,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
),
],
),
SizedBox(height: 10.0),
Container(
decoration: BoxDecoration(
border: Border.all(color: kPrimaryAppColor),
),
child: Padding(
padding: const EdgeInsets.all(6.0),
child: Column(
children: [
ListView(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
children: [
...entryCardList,
],
),
],
),
),
),
],
),
);
}
void saveForm2() {
keyForm.forEach((element) {
element.currentState.saveForm();
});
print("inside save form");
// if (formKey.currentState.validate()) {
// formKey.currentState.save();
// print(widget.taskEntry.taskName);
// print(widget.taskEntry.taskHours);
// }
}
}
class EntryCard extends StatefulWidget {
final TaskEntry taskEntry;
final int index;
final Function(int, EntryCard) removeEntryCard;
// final TextEditingController hours;
// final TextEditingController task;
const EntryCard(this.removeEntryCard,
{Key key, @required this.index, this.taskEntry})
: super(key: key);
void remove(int entryIndex) {
print("Called remove on $entryIndex" + this.hashCode.toString());
removeEntryCard(entryIndex, this);
}
@override
EntryCardState createState() {
return EntryCardState(index, remove);
}
}
class EntryCardState extends State<EntryCard> {
final int entryIndex;
final Function remove;
final formKey = GlobalKey<FormState>();
EntryCardState(this.entryIndex, this.remove);
@override
Widget build(BuildContext context) {
return Form(
key: formKey,
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: TextFormField(
// initialValue: widget.user.fullName,
onSaved: (val) => widget.taskEntry.taskHours = val,
validator: (val) => val.length > 1 ? null : 'Invalid Field',
// controller: widget.hours,
decoration: InputDecoration(
hintText: "Hours ${widget.index}",
isDense: true,
// border: OutlineInputBorder(),
),
),
),
SizedBox(width: 5.0),
Expanded(
child: TextFormField(
onSaved: (val) => widget.taskEntry.taskName = val,
validator: (val) => val.length > 1 ? null : 'Invalid Field',
// controller: widget.task,
decoration: InputDecoration(
hintText: "Task Name ${widget.index}",
// border: OutlineInputBorder(),
isDense: true,
),
),
),
IconButton(
icon: Icon(Icons.remove),
color: kPrimaryAppColor,
onPressed: () {
widget.remove(entryIndex);
},
)
],
),
SizedBox(height: 5.0),
// TextFormField(
// decoration: InputDecoration(
// hintText: "This is Remarks ${index}",
// border: O`utlineInputBorder(),
// ),
// ),
// SizedBox(height: 10.0),
],
),
);
}
void saveForm() {
print("inside save form");
if (formKey.currentState.validate()) {
formKey.currentState.save();
print(widget.taskEntry.taskName);
print(widget.taskEntry.taskHours);
}
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: AddTimesheet(),
);
}
}
导入“包装:颤振/材料.省道”;
常量颜色kPrimaryAppColor=Colors.blue;
TextStyle kDefaultTitleStyle=TextStyle(颜色:Colors.black);
TextStyle kDefaultParagraphStyle=TextStyle(颜色:Colors.black);
类任务条目{
字符串taskName;
字符串任务时间;
TaskEntry({this.taskName='',this.taskhurs=''});
字符串toString(){
返回'Student:{TaskName:$TaskName,taskhurs:$taskhurs}';
}
}
列表键=[
GlobalKey(),
GlobalKey()
];
//final keyForm=GlobalKey();
类AddTimesheet扩展StatefulWidget{
@凌驾
_AddTimesheetState createState()=>\u AddTimesheetState();
}
类_AddTimesheetState扩展状态{
字符串dropdownValue='Week 1';
//列出taskEntries=[];
List entriesWidgets=[];
//var卡=[];
提交数据(){
打印(“内部提交”);
key.forEach((元素){
element.currentState.saveForm2();
});
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(),
正文:SingleChildScrollView(
物理:物理(),
孩子:填充(
填充:常数边集全部(16.0),
子:列(
mainAxisSize:mainAxisSize.min,
crossAxisAlignment:crossAxisAlignment.start,
儿童:[
居中(
子:文本(
“Naman Ambavi-1405”,
样式:TextStyle(
fontWeight:fontWeight.w600,
字体大小:20.0,
颜色:kPrimaryAppColor,
),
),
),
尺寸箱(高度:15.0),
文本(“周”,样式:kDefaultTitleStyle),
容器(
宽度:300,
孩子:下拉按钮(
是的,
value:dropdownValue,
图标:图标(图标。向下箭头),
iconSize:24,
海拔:16,
样式:TextStyle(颜色:kPrimaryAppColor),
下划线:容器(
身高:2,
颜色:kPrimaryAppColor,
),
onChanged:(字符串newValue){
设置状态(){
dropdownValue=newValue;
});
},
项目:[
“第一周”,
“第2周(10月1日至10月10日)”,
“第3周”
].map((字符串值){
返回下拉菜单项(
价值:价值,
子项:文本(值),
);
}).toList(),
),
),
大小盒子(
身高:18.0,
),
常数分频器(
颜色:kPrimaryAppColor,
厚度:0.5,
),
文本(“选择部门”,样式:kDefaultTitleStyle),
尺寸箱(高度:20.0),
划船(
mainAxisAlignment:mainAxisAlignment.spaceBetween,
儿童:[
扁平按钮(
颜色:kPrimaryAppColor,
textColor:Colors.white,
禁用颜色:颜色。灰色,
disabledTextColor:Colors.black,
填充:边缘设置。全部(8.0),
splashColor:kPrimaryAppColor,
已按下:(){
/*...*/
},
子:文本(
“它”,
样式:TextStyle(fontSize:20.0),
),
),
扁平按钮(
颜色:kPrimaryAppColor,
textColor:Colors.white,
禁用颜色:颜色。灰色,
disabledTextColor:Colors.black,
填充:边缘设置。全部(8.0),
splashColor:kPrimaryAppColor,
已按下:(){
/*...*/
},
子:文本(
“PMT”,
样式:TextStyle(fontSize:20.0),
),
),
扁平按钮(
颜色:kPrimaryAppColor,
textColor:Colors.white,
禁用颜色:颜色。灰色,
disabledTextColor:Colors.black,
填充:边缘设置。全部(8.0),
splashColor:kPrimaryAppColor,
已按下:(){
/*...*/
},
子:文本(
“AV”,
样式:TextStyle(fontSize:20.0),
),
),
],
),
尺寸箱(高度:15.0),
划船(
mainAxisAlignment:mainAxisAlignment.spaceBetween,
儿童:[
正文(
“每周IT时间:35/40小时”,
风格:kDefaultParagraphSty
import 'package:flutter/material.dart';
const Color kPrimaryAppColor = Colors.blue;
TextStyle kDefaultTitleStyle = TextStyle(color: Colors.black);
TextStyle kDefaultParagraphStyle = TextStyle(color: Colors.black);
class TaskEntry {
String taskName;
String taskHours;
TaskEntry({this.taskName = '', this.taskHours = ''});
String toString() {
return 'Student: {TaskName: $taskName, TaskHours: $taskHours}';
}
}
List<GlobalKey<EntriesWidgetState>> key = [
GlobalKey<EntriesWidgetState>(),
GlobalKey<EntriesWidgetState>()
];
//final keyForm = GlobalKey<EntryCardState>();
class AddTimesheet extends StatefulWidget {
@override
_AddTimesheetState createState() => _AddTimesheetState();
}
class _AddTimesheetState extends State<AddTimesheet> {
String dropdownValue = 'Week 1';
// List<TaskEntry> taskEntries = [];
List<EntriesWidget> entriesWidgets = [];
// var cards = <Card>[];
submitData() {
print("inside submit");
key.forEach((element) {
element.currentState.saveForm2();
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: SingleChildScrollView(
physics: ScrollPhysics(),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Text(
'Naman Ambavi - 1405',
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 20.0,
color: kPrimaryAppColor,
),
),
),
SizedBox(height: 15.0),
Text('Week', style: kDefaultTitleStyle),
Container(
width: 300,
child: DropdownButton(
isExpanded: true,
value: dropdownValue,
icon: Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: TextStyle(color: kPrimaryAppColor),
underline: Container(
height: 2,
color: kPrimaryAppColor,
),
onChanged: (String newValue) {
setState(() {
dropdownValue = newValue;
});
},
items: <String>[
'Week 1',
'Week 2 (1st Oct - 10th Oct)',
'Week 3'
].map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
),
SizedBox(
height: 18.0,
),
const Divider(
color: kPrimaryAppColor,
thickness: 0.5,
),
Text('Select Department', style: kDefaultTitleStyle),
SizedBox(height: 20.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
FlatButton(
color: kPrimaryAppColor,
textColor: Colors.white,
disabledColor: Colors.grey,
disabledTextColor: Colors.black,
padding: EdgeInsets.all(8.0),
splashColor: kPrimaryAppColor,
onPressed: () {
/*...*/
},
child: Text(
"IT",
style: TextStyle(fontSize: 20.0),
),
),
FlatButton(
color: kPrimaryAppColor,
textColor: Colors.white,
disabledColor: Colors.grey,
disabledTextColor: Colors.black,
padding: EdgeInsets.all(8.0),
splashColor: kPrimaryAppColor,
onPressed: () {
/*...*/
},
child: Text(
"PMT",
style: TextStyle(fontSize: 20.0),
),
),
FlatButton(
color: kPrimaryAppColor,
textColor: Colors.white,
disabledColor: Colors.grey,
disabledTextColor: Colors.black,
padding: EdgeInsets.all(8.0),
splashColor: kPrimaryAppColor,
onPressed: () {
/*...*/
},
child: Text(
"AV",
style: TextStyle(fontSize: 20.0),
),
),
],
),
SizedBox(height: 15.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'IT Hours for week: 35/40 hours',
style: kDefaultParagraphStyle,
),
Chip(
label: Text('View Log'),
backgroundColor: Colors.grey,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
],
),
SizedBox(height: 20.0),
// Expanded(
// child: ListView.builder(
// itemCount: cards.length,
// itemBuilder: (BuildContext context, int index) {
// return cards[index];
// },
// ),
// ),
SizedBox(height: 20.0),
// EntriesWidget(),
Flexible(
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: 2,
itemBuilder: (context, index) {
return EntriesWidget(key: key[index]);
},
),
),
SizedBox(height: 20.0),
Center(
child: FlatButton(
color: kPrimaryAppColor,
textColor: Colors.white,
disabledColor: Colors.grey,
disabledTextColor: Colors.black,
padding: EdgeInsets.all(8.0),
splashColor: kPrimaryAppColor,
onPressed: submitData,
child: Text(
"Add Log",
style: TextStyle(fontSize: 20.0),
),
),
),
],
),
),
),
);
}
void onSave() {
// entries.forEach((form) => allValid = allValid && form.isValid());
// var data = taskEntries.map((it) => it.taskEntries).toList();
}
}
class EntriesWidget extends StatefulWidget {
EntriesWidget({Key key}) : super(key: key);
@override
EntriesWidgetState createState() => EntriesWidgetState();
}
class EntriesWidgetState extends State<EntriesWidget> {
List<EntryCard> entryCardList = [];
int count = 0;
List<GlobalKey<EntryCardState>> keyForm = [];
int keyFormIndex = -1;
void removeEntryCard(index, EntryCard) {
print("inside remove function ${index}");
keyFormIndex = keyFormIndex - 1;
var pos = entryCardList.indexOf(EntryCard);
print("pos $pos");
setState(() {
entryCardList.removeAt(pos);
keyForm.removeAt(pos);
// index++;
});
}
void addEntryCard() {
setState(() {
keyForm.add(GlobalKey<EntryCardState>());
keyFormIndex = keyFormIndex + 1;
entryCardList.add(
EntryCard(
removeEntryCard,
key: keyForm[keyFormIndex],
index: entryCardList.length,
taskEntry: TaskEntry(),
),
);
});
}
@override
void initState() {
// addEntryCard(); //Initialize with 1 item
super.initState();
}
@override
Widget build(BuildContext context) {
return Material(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('1. HRD Timesheet (Systems)', style: kDefaultTitleStyle),
GestureDetector(
onTap: addEntryCard,
child: Chip(
label: Text('+ Add Task'),
backgroundColor: Colors.grey,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
),
],
),
SizedBox(height: 10.0),
Container(
decoration: BoxDecoration(
border: Border.all(color: kPrimaryAppColor),
),
child: Padding(
padding: const EdgeInsets.all(6.0),
child: Column(
children: [
ListView(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
children: [
...entryCardList,
],
),
],
),
),
),
],
),
);
}
void saveForm2() {
keyForm.forEach((element) {
element.currentState.saveForm();
});
print("inside save form");
// if (formKey.currentState.validate()) {
// formKey.currentState.save();
// print(widget.taskEntry.taskName);
// print(widget.taskEntry.taskHours);
// }
}
}
class EntryCard extends StatefulWidget {
final TaskEntry taskEntry;
final int index;
final Function(int, EntryCard) removeEntryCard;
// final TextEditingController hours;
// final TextEditingController task;
const EntryCard(this.removeEntryCard,
{Key key, @required this.index, this.taskEntry})
: super(key: key);
void remove(int entryIndex) {
print("Called remove on $entryIndex" + this.hashCode.toString());
removeEntryCard(entryIndex, this);
}
@override
EntryCardState createState() {
return EntryCardState(index, remove);
}
}
class EntryCardState extends State<EntryCard> {
final int entryIndex;
final Function remove;
final formKey = GlobalKey<FormState>();
EntryCardState(this.entryIndex, this.remove);
@override
Widget build(BuildContext context) {
return Form(
key: formKey,
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: TextFormField(
// initialValue: widget.user.fullName,
onSaved: (val) => widget.taskEntry.taskHours = val,
validator: (val) => val.length > 1 ? null : 'Invalid Field',
// controller: widget.hours,
decoration: InputDecoration(
hintText: "Hours ${widget.index}",
isDense: true,
// border: OutlineInputBorder(),
),
),
),
SizedBox(width: 5.0),
Expanded(
child: TextFormField(
onSaved: (val) => widget.taskEntry.taskName = val,
validator: (val) => val.length > 1 ? null : 'Invalid Field',
// controller: widget.task,
decoration: InputDecoration(
hintText: "Task Name ${widget.index}",
// border: OutlineInputBorder(),
isDense: true,
),
),
),
IconButton(
icon: Icon(Icons.remove),
color: kPrimaryAppColor,
onPressed: () {
widget.remove(entryIndex);
},
)
],
),
SizedBox(height: 5.0),
// TextFormField(
// decoration: InputDecoration(
// hintText: "This is Remarks ${index}",
// border: O`utlineInputBorder(),
// ),
// ),
// SizedBox(height: 10.0),
],
),
);
}
void saveForm() {
print("inside save form");
if (formKey.currentState.validate()) {
formKey.currentState.save();
print(widget.taskEntry.taskName);
print(widget.taskEntry.taskHours);
}
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: AddTimesheet(),
);
}
}