I'm trying to push kombiController.text value to a new class, but after trying all sorts of things, I just don't know what else to do. I'm getting an error "8 positional arguments expected, but found 0, which I'm guessing is due to my FeedbackForm class requiring 8, but I don't find solution to how to fix it or set up some default paramaters.
Note: The other variable message-ekipaController is getting sent normally and I had no troubles implementing it.
I've been trying to fix and find a solution to this "little" problem for 2 days now and no matter from which angle I try to resolve this issue, I just get new problems somewhere else.
mainscreen.dart
import 'package:flutter/material.dart';
import 'secondscreen.dart';
import 'models/feedback_form.dart';
import 'package:flutter/widgets.dart';
class MainScreen extends StatefulWidget {
MainScreen({Key key}) : super(key: key);
#override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
String kombi;
String valuePolja;
TextEditingController ekipaController = new TextEditingController();
TextEditingController kombiController = new TextEditingController();
// Default Drop Down Item.
String dropdownValue = 'Tom Cruise';
// To show Selected Item in Text.
String holder = '' ;
List listItem = [
"1", "2", "3", "4", "5"
];
void getDropDownItem(){
setState(() {
holder = dropdownValue ;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("DHL"),
),
body: Center(
child: Column(
children: <Widget> [
TextFormField(
controller: ekipaController,
onChanged: (text) {
valuePolja = text;
},
validator: (value){
if(value.isEmpty){
return "Enter Valid Name";
}else{
return null;
}
},
decoration: InputDecoration(
hintText: "Ime Ekipe",
),
),
DropdownButton(
hint: Text("Izberi Kombi: "),
dropdownColor: Colors.white,
icon: Icon(Icons.arrow_drop_down),
value: kombi,
onChanged: (newValue) {
setState(() {
kombi = newValue;
});
kombiController.text = newValue;
},
items: listItem.map((valueItem) {
return DropdownMenuItem(
value: valueItem,
child: Text(valueItem),
);
}).toList(),
),
Padding(
padding: EdgeInsets.only(top: 30, bottom: 30),
child :
//Printing Item on Text Widget
Text('Selected Item = ' + kombiController.text,
style: TextStyle (fontSize: 22, color: Colors.black))),
ElevatedButton(
child: Text('Next Screen',
style: TextStyle(
color: Colors.white,
),
),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => SecondScreen(message: ekipaController.text)));
Navigator.push(context,
MaterialPageRoute(builder: (context) => FeedbackForm(kombiController: kombiController.text)));
}
),
],
),
)
);
}
}
feedback_form.dart
import 'package:dhl_app/mainscreen.dart';
import 'package:flutter/widgets.dart';
class FeedbackForm extends StatefulWidget {
const FeedbackForm(this.ime_ekipe, this.ime_stranke, this.postna_stevilka, this.teza, this.type, this.datum, this.dostavljeno, this.kombiController);
final String kombiController;
final String ime_ekipe;
final String ime_stranke;
final String postna_stevilka;
final String teza;
final String type;
final String datum;
final String dostavljeno;
//FeedbackForm(this._ime_ekipe, this._ime_stranke, this._postna_stevilka, this._teza, this._type, this._datum, this._dostavljeno, this.kombiController);
String toParams() => "?ime_ekipe=$ime_ekipe&ime_stranke=$ime_stranke&postna_stevilka=$postna_stevilka&teza=$teza&type=$type&datum=$datum&dostavljeno=$dostavljeno&kombi=$kombiController";
#override
State<StatefulWidget> createState() {
// TODO: implement createState
throw UnimplementedError();
}
}
secondscreen.dart (where the other variable works)
import 'package:flutter/material.dart';
import 'models/controller.dart';
import 'models/feedback_form.dart';
import 'mainscreen.dart';
class SecondScreen extends StatefulWidget {
final String message;
const SecondScreen({Key key, this.message}) : super(key: key);
#override
_SecondScreen createState() => _SecondScreen();
}
class _SecondScreen extends State<SecondScreen> {
var _controller = TextEditingController();
final _formKey = GlobalKey<FormState>();
final _scaffoldKey = GlobalKey<ScaffoldState>();
//TextField Controllers
TextEditingController nameController = TextEditingController();
TextEditingController emailController = TextEditingController();
TextEditingController phoneNumberController = TextEditingController();
TextEditingController feedbackController = TextEditingController();
TextEditingController typeController = TextEditingController();
TextEditingController dateController = TextEditingController();
TextEditingController dostavljenoController = TextEditingController();
TextEditingController kombiController = TextEditingController();
void _submitForm(){
if(_formKey.currentState.validate()) {
FeedbackForm feedbackForm = FeedbackForm(
nameController.text,
emailController.text,
phoneNumberController.text,
feedbackController.text,
typeController.text,
dateController.text,
dostavljenoController.text,
kombiController.text,
);
FormController formController = FormController(
(String response) {
print(response);
if(response == FormController.STATUS_SUCCESS){
_showSnackBar("Feedback Submitted!");
}else {
_showSnackBar("Error Occured!");
}
});
_showSnackBar("Submitting Feedback");
formController.submitForm(feedbackForm);
}
}
_showSnackBar(String message) {
final snackBar = SnackBar(content: Text(message),);
_scaffoldKey.currentState.showSnackBar(snackBar);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Vnesi Podatke"),
),
key: _scaffoldKey,
body: Form(
key: _formKey,
child: Container(
padding: EdgeInsets.symmetric(vertical: 50, horizontal: 24),
child: Column(
children: <Widget> [
TextFormField(
controller: nameController,
validator: (value){
if(value.isEmpty){
return "Enter Valid Name";
}else{
return null;
}
},
decoration: InputDecoration(
hintText: "${widget.message}",
suffixIcon: IconButton(
onPressed: () => nameController.clear(),
icon: Icon(Icons.clear),
),
),
),
TextFormField(
controller: emailController,
validator: (value){
if(value.isEmpty){
return "Enter Valid Email";
}else{
return null;
}
},
decoration: InputDecoration(
hintText: "Ime Stranke",
suffixIcon: IconButton(
onPressed: () => emailController.clear(),
icon: Icon(Icons.clear),
),
),
),
TextFormField(
controller: phoneNumberController,
validator: (value){
if(value.isEmpty){
return "Enter Valid Mobile Number";
}else{
return null;
}
},
decoration: InputDecoration(
hintText: "Poštna Številka",
suffixIcon: IconButton(
onPressed: () => phoneNumberController.clear(),
icon: Icon(Icons.clear),
),
),
),
TextFormField(
controller: feedbackController,
validator: (value){
if(value.isEmpty){
return "Enter Valid Feedback";
}else{
return null;
}
},
decoration: InputDecoration(
hintText: "Kilogramov",
suffixIcon: IconButton(
onPressed: () => feedbackController.clear(),
icon: Icon(Icons.clear),
),
),
),
TextFormField(
controller: typeController,
validator: (value){
if(value.isEmpty){
return "Enter Valid Feedback";
}else{
return null;
}
},
decoration: InputDecoration(
hintText: "Tip",
suffixIcon: IconButton(
onPressed: () => typeController.clear(),
icon: Icon(Icons.clear),
),
),
),
TextFormField(
controller: dateController,
validator: (value){
if(value.isEmpty){
return "Enter Valid Feedback";
}else{
return null;
}
},
decoration: InputDecoration(
hintText: "Datum",
suffixIcon: IconButton(
onPressed: () => dateController.clear(),
icon: Icon(Icons.clear),
),
),
),
TextFormField(
controller: dostavljenoController,
validator: (value){
if(value.isEmpty){
return "Enter Valid Feedback";
}else{
return null;
}
},
decoration: InputDecoration(
hintText: "Dostavljeno",
suffixIcon: IconButton(
onPressed: () => dostavljenoController.clear(),
icon: Icon(Icons.clear),
),
),
),
RaisedButton(
color: Colors.blue,
textColor: Colors.white,
onPressed: _submitForm,
child: Text('Submit Feedback'),
)
],
)
),
)
);
}
}
Related
Recently implemented a tagForm widget at "+" button press, I want to delete those widgets now at "delete" button press, but right now, even when I press the "delete" button, nothing happens.
How can I solve this?
Any help appreciated!
code:
import 'package:flutter/material.dart';
import '../database/firestoreHandler.dart';
import '../models/todo2.dart';
import '../widgets/dialogs.dart';
class TodoEdit extends StatefulWidget {
String? doctitle;
String? doctdescription;
String? docimage;
String? docid;
List? doctags;
TodoEdit({Key? key, this.doctitle, this.doctdescription, this.docimage, this.docid,this.doctags}) : super(key: key);
#override
_TodoEditState createState() => _TodoEditState();
}
class _TodoEditState extends State<TodoEdit> {
final _formKey = GlobalKey<FormState>();
final tcontroller = TextEditingController();
final dcontroller = TextEditingController();
final icontroller = TextEditingController();
var textEditingControllers = <TextEditingController>[];
//-----------------the list where the form is stored----------
var textformFields = <Widget>[];
void _addformWidget(controller) {
setState(() {
textformFields.add(tagForm(controller));
});
}
//------------------------------------------------------------------------
Widget tagForm(controller){
return TextFormField(
controller: controller,
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
labelText: "Tag",
labelStyle: TextStyle(color: Colors.white60),
fillColor: Colors.black,
filled: true,
suffixIcon: IconButton(
icon:Icon(Icons.delete, color: Colors.white,),
//--------------------- doesn't work?-------------------
onPressed: (){
setState(() {
textformFields.remove(tagForm(controller));
});
},
--------------------------------------------------------------
)
),
);
}
//-----------------------------------------------------------
#override
void initState() {
super.initState();
tcontroller.text = widget.doctitle.toString();
dcontroller.text = widget.doctdescription.toString();
icontroller.text = widget.docimage.toString();
widget.doctags?.forEach((element) {
var textEditingController = new TextEditingController(text: element);
textEditingControllers.add(textEditingController);
//return textformFields.add(tagForm(textEditingController)
return _addformWidget(textEditingController);
//);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[900],
appBar: AppBar(
actions: [
IconButton(onPressed: (){
showDialog(
barrierDismissible: false,
context: context,
builder: (context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
title: Text('Delete TODO'),
actions: [
TextButton(
child: Text('Cancel'),
onPressed: () {
Navigator.pop(context);
},
),
TextButton(
child: Text('Delete'),
onPressed: () {
deleteData(widget.docid.toString(), context);
setState(() {
showSnackBar(context, 'todo "${widget.doctitle}" successfully deleted!');
});
},
),
],
);
},
);
},
icon: Icon(Icons.delete))
],
backgroundColor: Colors.grey[900],
title: Text("${widget.doctitle}"),
),
body: Container(
child: SafeArea(
child: Form(
key: _formKey,
child: Column(
children: [
SizedBox(height: 10),
TextFormField(
controller: tcontroller,
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
labelText: "Title",
labelStyle: TextStyle(color: Colors.white60),
fillColor: Colors.black,
filled: true,
),
),
SizedBox(height: 10),
TextFormField(
controller: dcontroller,
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
labelText: "Description",
labelStyle: TextStyle(color: Colors.white60),
fillColor: Colors.black,
filled: true,
),
),
SizedBox(height: 10),
TextFormField(
controller: icontroller,
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
labelText: "Image url",
labelStyle: TextStyle(color: Colors.white60),
fillColor: Colors.black,
filled: true,
),
),
SizedBox(height: 10),
Row(children: [
Text("Tags:", style:TextStyle(color: Colors.white)),
IconButton(onPressed: (){
var textEditingController = new TextEditingController(text: "tag");
textEditingControllers.add(textEditingController);
_addformWidget(textEditingController);
print(textformFields.length);
},
icon: Icon(Icons.add,color: Colors.white,),
)
],),
/*SingleChildScrollView(
child: new Column(
children: textformFields,
)
),*/
Expanded(
child: SizedBox(
height: 200.0,
child: ListView.builder(
itemCount: textformFields.length,
itemBuilder: (context,index) {
return textformFields[index];
}),
)
),
],
),
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: (){
List<String> test = [];
textEditingControllers.forEach((element) {
test.add(element.text);
});
if(tcontroller == '' && dcontroller == '' && icontroller == ''){
print("not valid");
}else{
var todo = Todo2(
title: tcontroller.text,
description: dcontroller.text,
image: icontroller.text,
tags: test,
);
updateData(todo, widget.docid.toString(),context);
setState(() {
showSnackBar(context, 'todo ${widget.doctitle} successfully updated!');
});
}
},
child: Icon(Icons.update),
),
);
}
}
You can't remove anything from the list with objects from tagForm(controller), because these objects are newly created and therefore not the same as in the list (as long as the == operator is not overwritten)
If you still want to have the widgets in a list instead of just storing the controllers and without having to change much, you could remove the widgets like this:
onPressed: (){
setState(() {
controller.dispose();
textEditingControllers.remove(controller);
textformFields.removeWhere((w) => w.controller = controller));
});
},
and change the type of your List: var textformFields = <TextFormField>[]; and of the method TextFormField tagForm(controller).
In general, you can of course optimize the state management, but with this solution it should work for now.
Dont't store Widget, it is bad way. Insteads store there property, render by List then remove by index when you need.
ps: some code syntax can wrong, i write this on browser.
class _TodoEditState extends State<TodoEdit> {
...
var textformFields = <String>[];
...
void _addformWidget([String? initValue]) {
setState(() => textformFields.add(initValue ?? ""));
}
...
Widget tagForm(String value, void Function(String) onChange, void Function() onRemove){
var openEditor = () {
// Open dialog with text field to edit from [value] call onChange with
// new value
OpenDialog().then((newvalue) {
if(newvalue != null) onChange(newvalue);
}
};
var delete = () {
// Open confirm dialog then remove
OpenConfirmDialog("your message").then((continue) {
if(continue) onRemove();
});
};
return InkWell(
onTap: openEditor,
child: Text(value), // render your tag value
);
}
...
#override
void initState() {
...
textformFields = List.filled(widget.doctags ?? 0, ""); // or List.generate/map if you want replace by own value.
}
...
#override
Widget build(BuildContext context) {
...
ListView.builder(
itemCount: textformFields.length,
itemBuilder: (context,index) => tagForm(
textformFields[index],
(newvalue) => setState(() => textformFields[index] = newvalue),
() => setState(() => textformFields = textformFields..removeAt(index));,
),
),
...
);
}
I'm having troubles with my list builder.
I'm trying to add more TextFormFields when the "+" button next to the "Tag" text is pressed, I'm fetching the tag list from firebase and then displaying every tag from that list in a separate TextFormField, but when I try to add a new TextFormField with the "+" button, nothing happens, I check if the list leght changes and indeed it changes, but nothing happens, what I would expect is to get a new TextFormField in the red square.
code:
import 'package:flutter/material.dart';
import '../database/firestoreHandler.dart';
import '../models/todo2.dart';
import '../widgets/dialogs.dart';
class TodoEdit extends StatefulWidget {
String? doctitle;
String? doctdescription;
String? docimage;
String? docid;
List? doctags;
TodoEdit({Key? key, this.doctitle, this.doctdescription, this.docimage, this.docid,this.doctags}) : super(key: key);
#override
_TodoEditState createState() => _TodoEditState();
}
// -----------------------------my widget------------
Widget tagForm(controller){
return TextFormField(
controller: controller,
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
labelText: "Tag",
labelStyle: TextStyle(color: Colors.white60),
fillColor: Colors.black,
filled: true,
),
);
}
//---------------------------------------------------
class _TodoEditState extends State<TodoEdit> {
final _formKey = GlobalKey<FormState>();
final tcontroller = TextEditingController();
final dcontroller = TextEditingController();
final icontroller = TextEditingController();
//--------------------add widget to list----------------
void _addformWidget(list,controller) {
setState(() {
list.add(tagForm(controller));
});
}
//------------------------------------------------
#override
void initState() {
super.initState();
tcontroller.text = widget.doctitle.toString();
dcontroller.text = widget.doctdescription.toString();
icontroller.text = widget.docimage.toString();
}
#override
Widget build(BuildContext context) {
//----------I add the tags to the list view for the first time-----
var textEditingControllers = <TextEditingController>[];
var textformFields = <Widget>[];
widget.doctags?.forEach((element) {
var textEditingController = new TextEditingController(text: element);
textEditingControllers.add(textEditingController);
//return textformFields.add(tagForm(textEditingController)
return _addformWidget(textformFields, textEditingController);
//);
});
//------------------------------------------
return Scaffold(
backgroundColor: Colors.grey[900],
appBar: AppBar(
actions: [
IconButton(onPressed: (){
showDialog(
barrierDismissible: false,
context: context,
builder: (context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
title: Text('Delete TODO'),
actions: [
TextButton(
child: Text('Cancel'),
onPressed: () {
Navigator.pop(context);
},
),
TextButton(
child: Text('Delete'),
onPressed: () {
deleteData(widget.docid.toString(), context);
setState(() {
showSnackBar(context, 'todo "${widget.doctitle}" successfully deleted!');
});
},
),
],
);
},
);
},
icon: Icon(Icons.delete))
],
backgroundColor: Colors.grey[900],
title: Text("${widget.doctitle}"),
),
body: Container(
child: SafeArea(
child: Form(
key: _formKey,
child: Column(
children: [
SizedBox(height: 10),
TextFormField(
controller: tcontroller,
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
labelText: "Title",
labelStyle: TextStyle(color: Colors.white60),
fillColor: Colors.black,
filled: true,
),
),
SizedBox(height: 10),
TextFormField(
controller: dcontroller,
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
labelText: "Description",
labelStyle: TextStyle(color: Colors.white60),
fillColor: Colors.black,
filled: true,
),
),
SizedBox(height: 10),
TextFormField(
controller: icontroller,
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
labelText: "Image url",
labelStyle: TextStyle(color: Colors.white60),
fillColor: Colors.black,
filled: true,
),
),
SizedBox(height: 10),
Row(children: [
Text("Tags:", style:TextStyle(color: Colors.white)),
//-----------------------here I try to add the new text form field-----------
IconButton(onPressed: (){
var textEditingController = new TextEditingController(text: "tag");
textEditingControllers.add(textEditingController);
_addformWidget(textformFields,textEditingController);
print(textformFields.length);
},
icon: Icon(Icons.add,color: Colors.white,),
)
],),//------------------------
/*SingleChildScrollView(
child: new Column(
children: textformFields,
)
),*/
//--------------------------------here I build my list--------------
Expanded(
child: SizedBox(
height: 200.0,
child: ListView.builder(
itemCount: textformFields.length,
itemBuilder: (context,index) {
return textformFields[index];
}),
)
),
],
),
),
),
),
//--------------------------------------------------
floatingActionButton: FloatingActionButton(
onPressed: (){
if(tcontroller == '' && dcontroller == '' && icontroller == ''){
print("not valid");
}else{
var todo = Todo2(
title: tcontroller.text,
description: dcontroller.text,
image: icontroller.text,
//tags: tagcontroller.text,
);
updateData(todo, widget.docid.toString(),context);
setState(() {
showSnackBar(context, 'todo ${widget.doctitle} successfully updated!');
});
}
},
child: Icon(Icons.update),
),
);
}
}
Any help appreciated!
Since you've kept the list of form fields and controllers in the build function, the widget isn't rebuilt when you call setState on them.
Instead move these to with other state variables.
final _formKey = GlobalKey<FormState>();
final tcontroller = TextEditingController();
final dcontroller = TextEditingController();
final icontroller = TextEditingController();
final textEditingControllers = <TextEditingController>[];
final textformFields = <Widget>[];
Now you can change the _addformWidget function to directly use the list without taking it as a parameter.
void _addformWidget(TextEditingController controller) {
setState(() {
textformFields.add(tagForm(controller));
});
}
Then initialise them in the initState function.
#override
void initState() {
super.initState();
tcontroller.text = widget.doctitle.toString();
dcontroller.text = widget.doctdescription.toString();
icontroller.text = widget.docimage.toString();
widget.doctags?.forEach((element) {
final textEditingController = new TextEditingController(text: element);
textEditingControllers.add(textEditingController);
//return textformFields.add(tagForm(textEditingController)
_addformWidget(textEditingController);
//);
});
}
This ideally should fix your problem. Let me know if it doesn't and if it does, you can click the check mark to confirm that.
//// Remove textEditingControllers and textformFields list from the build. And declare it on top.
#override
Widget build(BuildContext context) {
//----------I add the tags to the list view for the first time-----
var textEditingControllers = <TextEditingController>[];
var textformFields = <Widget>[];
//// Use like below
class _TodoEditState extends State<TodoEdit> {
final _formKey = GlobalKey<FormState>();
final tcontroller = TextEditingController();
final dcontroller = TextEditingController();
final icontroller = TextEditingController();
var textEditingControllers = <TextEditingController>[]; //<---------
var textformFields = <Widget>[];
////// Full Code
class TodoEdit extends StatefulWidget {
String? doctitle;
String? doctdescription;
String? docimage;
String? docid;
List? doctags;
TodoEdit(
{Key? key,
this.doctitle,
this.doctdescription,
this.docimage,
this.docid,
this.doctags})
: super(key: key);
#override
_TodoEditState createState() => _TodoEditState();
}
class _TodoEditState extends State<TodoEdit> {
final _formKey = GlobalKey<FormState>();
final tcontroller = TextEditingController();
final dcontroller = TextEditingController();
final icontroller = TextEditingController();
var textEditingControllers = <TextEditingController>[];
var textformFields = <Widget>[];
#override
void initState() {
widget.doctags?.forEach((element) {
var textEditingController = TextEditingController(text: element);
textEditingControllers.add(textEditingController);
//return textformFields.add(tagForm(textEditingController)
return _addformWidget(textformFields, textEditingController);
//);
});
super.initState();
tcontroller.text = widget.doctitle.toString();
dcontroller.text = widget.doctdescription.toString();
icontroller.text = widget.docimage.toString();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[900],
appBar: AppBar(
actions: [
IconButton(
onPressed: () {
showDialog(
barrierDismissible: false,
context: context,
builder: (context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
title: Text('Delete TODO'),
actions: [
TextButton(
child: Text('Cancel'),
onPressed: () {
Navigator.pop(context);
},
),
TextButton(
child: Text('Delete'),
onPressed: () {
deleteData(widget.docid.toString(), context);
setState(() {
showSnackBar(context,
'todo "${widget.doctitle}" successfully deleted!');
});
},
),
],
);
},
);
},
icon: Icon(Icons.delete))
],
backgroundColor: Colors.grey[900],
title: Text("${widget.doctitle}"),
),
body: Container(
child: SafeArea(
child: Form(
key: _formKey,
child: Column(
children: [
SizedBox(height: 10),
TextFormField(
controller: tcontroller,
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
labelText: "Title",
labelStyle: TextStyle(color: Colors.white60),
fillColor: Colors.black,
filled: true,
),
),
SizedBox(height: 10),
TextFormField(
controller: dcontroller,
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
labelText: "Description",
labelStyle: TextStyle(color: Colors.white60),
fillColor: Colors.black,
filled: true,
),
),
SizedBox(height: 10),
TextFormField(
controller: icontroller,
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
labelText: "Image url",
labelStyle: TextStyle(color: Colors.white60),
fillColor: Colors.black,
filled: true,
),
),
SizedBox(height: 10),
Row(
children: [
Text("Tags:", style: TextStyle(color: Colors.white)),
//-----------------------here I try to add the new text form field-----------
IconButton(
onPressed: () {
var textEditingController =
new TextEditingController(text: "tag");
textEditingControllers.add(textEditingController);
_addformWidget(textformFields, textEditingController);
print(textformFields.length);
},
icon: Icon(
Icons.add,
color: Colors.white,
),
)
],
), //------------------------
/*SingleChildScrollView(
child: new Column(
children: textformFields,
)
),*/
//--------------------------------here I build my list--------------
Expanded(
child: SizedBox(
height: 200.0,
child: ListView.builder(
itemCount: textformFields.length,
itemBuilder: (context, index) {
return textformFields[index];
}),
)),
],
),
),
),
),
//--------------------------------------------------
floatingActionButton: FloatingActionButton(
onPressed: () {
if (tcontroller == '' && dcontroller == '' && icontroller == '') {
print("not valid");
} else {
var todo = Todo2(
title: tcontroller.text,
description: dcontroller.text,
image: icontroller.text,
//tags: tagcontroller.text,
);
updateData(todo, widget.docid.toString(), context);
setState(() {
showSnackBar(
context, 'todo ${widget.doctitle} successfully updated!');
});
}
},
child: Icon(Icons.update),
),
);
}
//--------------------add widget to list----------------
void _addformWidget(list, controller) {
setState(() {
list.add(tagForm(controller));
});
}
// -----------------------------my widget------------
Widget tagForm(controller) {
return TextFormField(
controller: controller,
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
labelText: "Tag",
labelStyle: TextStyle(color: Colors.white60),
fillColor: Colors.black,
filled: true,
),
);
}
}
I'm making authentication login form and want to connect submitAuthForm Function to the AuthForm. That's why I pass reference in the AuthForm. I am beginner. Please help me to solve this problem (The argument type void Function(String, String, String, bool) can't be assigned to the parameter type void Function(String, String, String, bool)
Thanks.
class AuthScreen extends StatefulWidget {
#override
_AuthScreenState createState() => _AuthScreenState();
}
class _AuthScreenState extends State<AuthScreen> {
void _submitAuthForm(
String email,
String password,
String username,
bool isLogin) {
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).primaryColor,
body: Authform(_submitAuthForm,)/*( The argument type 'void Function(String, String, String, bool)' can't be assigned to the parameter type 'Void Function(String, String, String, bool)'.*/)
);
}
}
class Authform extends StatefulWidget {
Authform(this.submitFN);
final Void Function(
String email, String password, String username, bool isLogin) submitFN;
#override
_AuthformState createState() => _AuthformState();
}
class _AuthformState extends State<Authform> {
final _formKey = GlobalKey<FormState>();
var _isLogin = true;
var _userEmail;
var _userName;
var _userPassword;
void _trySubmit() {
final isValid = _formKey.currentState!.validate();
FocusScope.of(context).unfocus();
if (isValid) {
_formKey.currentState!.save();
widget.submitFN(_userEmail,_userPassword,_userName,_isLogin);
}
}
#override
Widget build(BuildContext context) {
return Center(
child: Card(
margin: EdgeInsets.all(20),
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(16),
child: Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
key: ValueKey('email'),
validator: (value) {
if (value!.isEmpty || !value.contains('#')) {
return 'please enter valid email address';
}
return null;
},
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
icon: Icon(
Icons.mail,
color: Colors.orange,
),
labelText: 'Email Addess'),
onSaved: (value) {
_userEmail = value;
},
),
if (!_isLogin)
TextFormField(
key: ValueKey('username'),
validator: (value) {
if (value!.isEmpty || value.length < 4) {
return 'Username is short enter atleast 4 characters ';
}
},
decoration: InputDecoration(
icon: Icon(
Icons.person,
color: Colors.orange,
),
labelText: 'Username'),
onSaved: (value) {
_userName = value;
},
),
TextFormField(
key: ValueKey('password'),
validator: (value) {
if (value!.isEmpty || value.length < 7) {
return 'Password must be atleast 7 characters long';
}
return null;
},
decoration: InputDecoration(
icon: Icon(
Icons.lock,
color: Colors.orange,
),
labelText: 'password',
),
obscureText: true,
onSaved: (value) {
_userPassword = value;
},
),
SizedBox(
height: 12,
),
ElevatedButton(
onPressed: _trySubmit,
child: Text(_isLogin ? 'Login' : 'Signup'),
style: ElevatedButton.styleFrom(onPrimary: Colors.white),
),
TextButton(
onPressed: () {
setState(() {
_isLogin = !_isLogin;
});
},
child: Text(_isLogin
? 'Create new account'
: 'I already have a acoount'))
],
)),
)),
),
);
}
}
When declaring a function or variable you have follow proper declaring method to avoid unusual issues. You have declare your function using Void the V is in capital case there but it must be in small case like void. Juts change this like :
final Void Function(
to
final void Function(
import 'package:flutter/material.dart';
void main(List<String> args) {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(),
home: AuthScreen(),
);
}
}
class AuthScreen extends StatefulWidget {
#override
_AuthScreenState createState() => _AuthScreenState();
}
class _AuthScreenState extends State<AuthScreen> {
void _submitAuthForm(
String email, String password, String username, bool isLogin) {}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).primaryColor,
body: Authform(
_submitAuthForm,
));
}
}
class Authform extends StatefulWidget {
Authform(this.submitFN);
final void Function(
String email, String password, String username, bool isLogin) submitFN;
#override
_AuthformState createState() => _AuthformState();
}
class _AuthformState extends State<Authform> {
final _formKey = GlobalKey<FormState>();
var _isLogin = true;
var _userEmail;
var _userName;
var _userPassword;
void _trySubmit() {
final isValid = _formKey.currentState!.validate();
FocusScope.of(context).unfocus();
if (isValid) {
_formKey.currentState!.save();
widget.submitFN(_userEmail, _userPassword, _userName, _isLogin);
}
}
#override
Widget build(BuildContext context) {
return Center(
child: Card(
margin: EdgeInsets.all(20),
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(16),
child: Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
key: ValueKey('email'),
validator: (value) {
if (value!.isEmpty || !value.contains('#')) {
return 'please enter valid email address';
}
return null;
},
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
icon: Icon(
Icons.mail,
color: Colors.orange,
),
labelText: 'Email Addess'),
onSaved: (value) {
_userEmail = value;
},
),
if (!_isLogin)
TextFormField(
key: ValueKey('username'),
validator: (value) {
if (value!.isEmpty || value.length < 4) {
return 'Username is short enter atleast 4 characters ';
}
},
decoration: InputDecoration(
icon: Icon(
Icons.person,
color: Colors.orange,
),
labelText: 'Username'),
onSaved: (value) {
_userName `enter code here`= value;
},
),
TextFormField(
key: ValueKey('password'),
validator: (value) {
if (value!.isEmpty || value.length < 7) {
return 'Password must be atleast 7 characters long';
}
return null;
},
decoration: InputDecoration(
icon: Icon(
Icons.lock,
color: Colors.orange,
),
labelText: 'password',
),
obscureText: true,
onSaved: (value) {
_userPassword = value;
},
),
SizedBox(
height: 12,
),
ElevatedButton(
onPressed: _trySubmit,
child: Text(_isLogin ? 'Login' : 'Signup'),
style: ElevatedButton.styleFrom(onPrimary: Colors.white),
),
TextButton(
onPressed: () {
setState(() {
_isLogin = !_isLogin;
});
},
child: Text(_isLogin
? 'Create new account'
: 'I already have a acoount'))
],
)),
)),
),
);
}
}
account_screen.dart
child: AuthForm(
submitFn: _submitAuthForm,
),
I have watched a couple of tutorials on how to make validators work but none of them seemed to work. Can anyone help me with this? This is the code of a simple sign in page. My validators don't show up on screen if there's any sort of error it should be detecting. I've watched tutorials where it shows up in red but in my app, it doesn't show up at all.
class UserLogin extends StatefulWidget {
UserLogin({this.auth,this.onSignedIn});
final BaseAuth auth;
final VoidCallback onSignedIn;
#override
State<StatefulWidget> createState()=> _UserLoginState();
}
class _UserLoginState extends State<UserLogin> {
final formkey = GlobalKey<FormState>();
bool _validateAndSave()
{
final form = formkey.currentState;
if(form.validate())
{
form.save();
return true;
}
else
return false;
}
static final incorrect_icon = Icon(
Icons.error,
color: Colors.pink,
);
void _validateAndSubmit() async
{
if(_validateAndSave()) {
try {
String userId = await widget.auth.signIn(emailid, password);
print('Signed in! $userId');
//widget.onSignedIn();
Navigator.push(context, MaterialPageRoute(builder: (context)=>Feed()));
}
catch (e) {
print('Error: $e');
}
}
}
static final TextEditingController emailContr = new TextEditingController();
static final TextEditingController passwordContr = new TextEditingController();
static String get emailid => emailContr.text;
static String get password => passwordContr.text;
final _email = Container(
padding: EdgeInsets.only(left: 10, right: 10),
child: TextFormField(
keyboardType: TextInputType.emailAddress,
controller: emailContr,
autofocus: false,
validator: (input) {
if(input.isEmpty)
{
return 'Email cannot be empty';
}
return null;
},
//onSaved: (input)=> emailid = input,
decoration: InputDecoration(
hintText: 'Enter Email Address',
suffixIcon: Icon(Icons.email),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10)
),
),
),
);
final _pass = Container(
padding: EdgeInsets.only(left: 10, right: 10),
child: TextFormField(
controller: passwordContr,
obscureText: true,
autofocus: false,
validator: (input) {
if(input.length <= 6)
{
return 'Password should be at least 6 characters';
}
return null;
},
decoration: InputDecoration(
hintText: 'Enter password',
suffixIcon: Icon(Icons.lock),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10)
),
),
),
);
/*final login_button =
},
);
*/
#override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Colors.yellow,
body: Container(
child: Form(
key: formkey,
child: Column(
children: <Widget>[
SizedBox(height: 200,),
Text('Vibing',
style:TextStyle(
fontWeight: FontWeight.bold,
fontSize: 64,
),
),
SizedBox(height: 100,),
_email,
SizedBox(height: 20,),
_pass,
SizedBox(height:30),
RaisedButton(
color: Colors.yellow,
elevation: 5,
child: Text('Login'),
onPressed: (){
_validateAndSubmit();
formkey.currentState.reset();
}
),
SizedBox(height:10),
FlatButton(
child: Text('Forgot password'),
onPressed: ()=> Navigator.push(context, MaterialPageRoute(builder:(context)=>ForgotPassword()),)
),
SizedBox(height:10),
FlatButton(
child: Text('New? Register here!'),
onPressed: ()=> Navigator.push(context, MaterialPageRoute(builder:(context)=>UserReg()),)
),
],
),
),
) ,
);
}
}
The problem is that you're resetting the form after validation so any error shown will reset. Just remove this line from your login button callback:
formkey.currentState.reset();
And voila:
reset():
Resets every [FormField] that is a descendant of this [Form] back to its
[FormField.initialValue].
In your case, the initialValue is empty string "" and that's why when you called reset() method of Form, it's setting an empty string, that will not show any error, as nothing is there.
I'm building an application that has a pretty long form with a lot of text fields, so I divided the text fields into multiple screens. It got three screens, the first screen has some common text fields such as phone, website, email, etc. The second screen has some more text fields and the same with the third screen. I'm trying to display all the details from the three forms at the end on a different screen.
I want to display all the details in the end when I hit the 'Done' button on a different page.
Here's the code for the first screen which has the first form:-
import 'package:flutter/material.dart';
import 'package:instaskool/model.dart';
import 'package:validators/validators.dart' as validator;
import 'package:instaskool/home_screens/homescreen_student.dart';
import 'package:instaskool/home_screens/homescreen_school.dart';
import 'package:instaskool/screens/school_signup_two.dart';
class SchoolReg extends StatefulWidget {
#override
_SchoolRegState createState() => _SchoolRegState();
}
class _SchoolRegState extends State<SchoolReg> {
final _formKey = GlobalKey<FormState>();
School school = School();
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: new Form(
key: _formKey,
child: Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 130),
alignment: Alignment.topCenter,
child: MyTextFormField(
hintText: 'School name',
validator: (String value) {
if (value.isEmpty) {
return 'Enter your school name';
}
return null;
},
onSaved: (String value) {
school.schoolName = value;
},
),
),
MyTextFormField(
hintText: 'Phone',
validator: (String value) {
if (value.isEmpty) {
return 'Enter the phone number';
}
return null;
},
onSaved: (String value) {
school.schoolPhone = value;
},
),
MyTextFormField(
hintText: 'Email',
validator: (String value) {
if (value.isEmpty) {
return 'Enter the email address';
}
return null;
},
onSaved: (String value) {
school.schoolEmail = value;
},
),
MyTextFormField(
hintText: 'School Website',
isEmail: true,
validator: (String value) {
if (value.isEmpty) {
return "Enter the school's website";
}
return null;
},
onSaved: (String value) {
school.schoolWebsite = value;
},
),
RaisedButton(
color: Colors.blueAccent,
onPressed: () {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SchoolRegTwo()));
}
},
child: Text(
'Next',
style: TextStyle(
color: Colors.white,
),
),
)
],
),
),
),
);
}
}
class MyTextFormField extends StatelessWidget {
final String hintText;
final Function validator;
final Function onSaved;
final bool isPassword;
final bool isEmail;
MyTextFormField({
this.hintText,
this.validator,
this.onSaved,
this.isPassword = false,
this.isEmail = false,
});
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(8.0),
child: TextFormField(
decoration: InputDecoration(
hintText: hintText,
contentPadding: EdgeInsets.all(15.0),
border: InputBorder.none,
filled: true,
fillColor: Colors.grey[200],
),
obscureText: isPassword ? true : false,
validator: validator,
onSaved: onSaved,
keyboardType: isEmail ? TextInputType.emailAddress : TextInputType.text,
),
);
}
}
Here's the code for the second form:-
import 'package:flutter/material.dart';
import 'package:instaskool/model.dart';
import 'package:validators/validators.dart' as validator;
import 'package:instaskool/home_screens/homescreen_student.dart';
import 'package:instaskool/home_screens/homescreen_school.dart';
import 'package:instaskool/screens/school_signup_three.dart';
class SchoolRegTwo extends StatefulWidget {
#override
_SchoolRegTwoState createState() => _SchoolRegTwoState();
}
class _SchoolRegTwoState extends State<SchoolRegTwo> {
final _formKey = GlobalKey<FormState>();
SchoolDet schooldet = SchoolDet();
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: new Form(
key: _formKey,
child: Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 130),
alignment: Alignment.topCenter,
child: MyTextFormField(
hintText: 'School address 1',
validator: (String value) {
if (value.isEmpty) {
return "Enter your school's address";
}
return null;
},
onSaved: (String value) {
schooldet.addressOne = value;
},
),
),
MyTextFormField(
hintText: 'School address 2',
validator: (String value) {
if (value.isEmpty) {
return "Enter the school's address";
}
return null;
},
onSaved: (String value) {
schooldet.addressTwo = value;
},
),
MyTextFormField(
hintText: 'City',
validator: (String value) {
if (value.isEmpty) {
return 'Enter the city';
}
return null;
},
onSaved: (String value) {
schooldet.city = value;
},
),
MyTextFormField(
hintText: 'Pincode',
isEmail: true,
validator: (String value) {
if (value.isEmpty) {
return "Enter the pincode";
}
return null;
},
onSaved: (String value) {
schooldet.pincode = value;
},
),
MyTextFormField(
hintText: 'State',
isEmail: true,
validator: (String value) {
if (value.isEmpty) {
return "Enter the state";
}
return null;
},
onSaved: (String value) {
schooldet.state = value;
},
),
RaisedButton(
color: Colors.blueAccent,
onPressed: () {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SchoolRegThree(schooldet: this.schooldet)));
}
},
child: Text(
'Next',
style: TextStyle(
color: Colors.white,
),
),
)
],
),
),
),
);
}
}
class MyTextFormField extends StatelessWidget {
final String hintText;
final Function validator;
final Function onSaved;
final bool isPassword;
final bool isEmail;
MyTextFormField({
this.hintText,
this.validator,
this.onSaved,
this.isPassword = false,
this.isEmail = false,
});
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(8.0),
child: TextFormField(
decoration: InputDecoration(
hintText: hintText,
contentPadding: EdgeInsets.all(15.0),
border: InputBorder.none,
filled: true,
fillColor: Colors.grey[200],
),
obscureText: isPassword ? true : false,
validator: validator,
onSaved: onSaved,
keyboardType: isEmail ? TextInputType.emailAddress : TextInputType.text,
),
);
}
}
Here's the code for the third form:-
import 'package:flutter/material.dart';
import 'package:instaskool/model.dart';
import 'package:validators/validators.dart' as validator;
import 'package:instaskool/home_screens/homescreen_student.dart';
import 'package:instaskool/home_screens/homescreen_school.dart';
import 'package:instaskool/screens/school_signup_three.dart';
import 'package:instaskool/screens/school_code.dart';
class SchoolRegThree extends StatefulWidget {
School school;
SchoolRegThree({this.school, SchoolDet schooldet});
#override
_SchoolRegThreeState createState() => _SchoolRegThreeState();
}
class _SchoolRegThreeState extends State<SchoolRegThree> {
final _formKey = GlobalKey<FormState>();
SchoolUser schooluser = SchoolUser();
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: new Form(
key: _formKey,
child: Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 100),
child: MyTextFormField(
hintText: 'Username',
isPassword: true,
validator: (String value) {
if (value.length < 5) {
return 'Username should be at least 5 characters long';
}
_formKey.currentState.save();
return null;
},
onSaved: (String value) {
schooluser.username = value;
},
),
),
MyTextFormField(
hintText: 'New Password',
isPassword: true,
validator: (String value) {
if (value.length < 7) {
return 'Password should be at least 7 characters long';
} else if (schooluser.password != null) {
print(value);
print(schooluser.password);
}
return null;
},
onSaved: (String value) {
schooluser.password = value;
},
),
RaisedButton(
color: Colors.blueAccent,
onPressed: () {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ResultSchool(schooluser: this.schooluser)));
}
},
child: Text(
'Done',
style: TextStyle(
color: Colors.white,
),
),
)
],
),
),
),
);
}
}
class MyTextFormField extends StatelessWidget {
final String hintText;
final Function validator;
final Function onSaved;
final bool isPassword;
final bool isEmail;
MyTextFormField({
this.hintText,
this.validator,
this.onSaved,
this.isPassword = false,
this.isEmail = false,
});
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(8.0),
child: TextFormField(
decoration: InputDecoration(
hintText: hintText,
contentPadding: EdgeInsets.all(15.0),
border: InputBorder.none,
filled: true,
fillColor: Colors.grey[200],
),
obscureText: isPassword ? true : false,
validator: validator,
onSaved: onSaved,
keyboardType: isEmail ? TextInputType.emailAddress : TextInputType.text,
),
);
}
}
Here's the model.dart which has all the variables:-
import 'package:flutter/material.dart';
import 'package:instaskool/screens/school_code.dart';
class Model {
String fullname;
String code;
String standard;
String section;
String username;
String password;
Model({this.fullname, this.code, this.standard, this.section, this.username, this.password});
}
class School {
String schoolName;
String schoolPhone;
String schoolEmail;
String schoolWebsite;
School({this.schoolName, this.schoolPhone, this.schoolEmail, this.schoolWebsite});
}
class SchoolDet {
String addressOne;
String addressTwo;
String city;
String pincode;
String state;
SchoolDet({this.addressOne, this.addressTwo, this.city, this.pincode, this.state});
}
class SchoolUser{
String username;
String password;
SchoolUser({this.username, this.password});
}
class SchoolCode{
String principalCode;
String teacherCode;
String studentCode;
SchoolCode({this.principalCode, this.teacherCode, this.studentCode});
}
Here's the result screen where I wanna display all the data:-
import 'package:flutter/material.dart';
import 'package:instaskool/model.dart';
class ResultSchool extends StatelessWidget {
School school;
SchoolDet schooldet;
SchoolCode schoolcode;
SchoolUser schooluser;
ResultSchool({this.school, this.schooldet, this.schooluser});
#override
Widget build(BuildContext context) {
return (Scaffold(
appBar: AppBar(title: Text('School details')),
body: Container(
margin: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(school.schoolName, style: TextStyle(fontSize: 22)),
Text(school.schoolPhone, style: TextStyle(fontSize: 22)),
Text(school.schoolEmail, style: TextStyle(fontSize: 22)),
Text(school.schoolWebsite, style: TextStyle(fontSize: 22)),
Text(schooldet.addressOne, style: TextStyle(fontSize: 22)),
Text(schooldet.addressTwo, style: TextStyle(fontSize: 22)),
Text(schooldet.city, style: TextStyle(fontSize: 22)),
Text(schooldet.pincode, style: TextStyle(fontSize: 22)),
Text(schooldet.state, style: TextStyle(fontSize: 22)),
Text(schooluser.username, style: TextStyle(fontSize: 22)),
Text(schooluser.password, style: TextStyle(fontSize: 22)),
Text(schoolcode.teacherCode, style: TextStyle(fontSize: 22)),
Text(schoolcode.principalCode, style: TextStyle(fontSize: 22)),
],
),
),
));
}
}
Add a widget to manage form transitions
enum SchoolFormPhase { BASIC_DTL, ADDRESS, USER_DTL }
class SchoolRegistration extends StatefulWidget {
#override
_SchoolRegistrationState createState() => _SchoolRegistrationState();
}
class _SchoolRegistrationState extends State<SchoolRegistration> {
SchoolFormPhase phase;
School schoolForm;
#override
void initState() {
phase = SchoolFormPhase.BASIC_DTL;
schoolForm = School();
super.initState();
}
#override
Widget build(BuildContext context) {
switch (phase) {
case SchoolFormPhase.BASIC_DTL:
return SchoolReg(
school: schoolForm,
onSaved: (school) {
setState(() {
schoolForm = school;
phase = SchoolFormPhase.ADDRESS;
});
});
case SchoolFormPhase.ADDRESS:
return SchoolRegTwo(
school: schoolForm,
onSaved: (school) {
setState(() {
schoolForm = school;
phase = SchoolFormPhase.USER_DTL;
});
});
case SchoolFormPhase.USER_DTL:
return SchoolRegThree(
school: schoolForm,
onSaved: (school) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ResultSchool(
schooluser: school.user,
school: school,
schooldet: school.address)));
},
);
}
return Container();
}
}
change the Form widget to accept inputs
class SchoolReg extends StatefulWidget {
final School school;
final Function(School) onSaved;
const SchoolReg({Key key, this.school, this.onSaved}) : super(key: key);
#override
_SchoolRegState createState() => _SchoolRegState();
}
class _SchoolRegState extends State<SchoolReg> {
final _formKey = GlobalKey<FormState>();
School _school;
#override
void initState() {
_school = widget.school;
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: new Form(
key: _formKey,
child: Column(children: <Widget>[
Container(
margin: EdgeInsets.only(top: 130),
alignment: Alignment.topCenter,
child: MyTextFormField(
hintText: 'School name',
validator: (String value) {
return value.isEmpty
? 'Enter your school name'
: null;
},
onSaved: (value) => _school.schoolName = value)),
MyTextFormField(
hintText: 'Phone',
validator: (String value) {
if (value.isEmpty) {
return 'Enter the phone number';
}
return null;
},
onSaved: (String value) {
_school.schoolPhone = value;
},
),
MyTextFormField(
hintText: 'Email',
validator: (String value) {
if (value.isEmpty) {
return 'Enter the email address';
}
return null;
},
onSaved: (String value) {
_school.schoolEmail = value;
},
),
MyTextFormField(
hintText: 'School Website',
isEmail: true,
validator: (String value) {
if (value.isEmpty) {
return "Enter the school's website";
}
return null;
},
onSaved: (String value) {
_school.schoolWebsite = value;
},
),
RaisedButton(
color: Colors.blueAccent,
onPressed: () {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
widget.onSaved(_school);
}
},
child:
Text('Next', style: TextStyle(color: Colors.white)))
]))));
}
}
form 2
class SchoolRegTwo extends StatefulWidget {
final School school;
final Function(School) onSaved;
const SchoolRegTwo({Key key, this.school, this.onSaved}) : super(key: key);
#override
_SchoolRegTwoState createState() => _SchoolRegTwoState();
}
class _SchoolRegTwoState extends State<SchoolRegTwo> {
final _formKey = GlobalKey<FormState>();
SchoolDet schooldet;
#override
void initState() {
schooldet = widget.school.address;
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: new Form(
key: _formKey,
child: Column(children: <Widget>[
Container(
margin: EdgeInsets.only(top: 130),
alignment: Alignment.topCenter,
child: MyTextFormField(
hintText: 'School address 1',
validator: (String value) {
if (value.isEmpty) {
return "Enter your school's address";
}
return null;
},
onSaved: (String value) {
schooldet.addressOne = value;
},
),
),
MyTextFormField(
hintText: 'School address 2',
validator: (String value) {
if (value.isEmpty) {
return "Enter the school's address";
}
return null;
},
onSaved: (String value) {
schooldet.addressTwo = value;
},
),
MyTextFormField(
hintText: 'City',
validator: (String value) {
if (value.isEmpty) {
return 'Enter the city';
}
return null;
},
onSaved: (String value) {
schooldet.city = value;
},
),
MyTextFormField(
hintText: 'Pincode',
isEmail: true,
validator: (String value) {
if (value.isEmpty) {
return "Enter the pincode";
}
return null;
},
onSaved: (String value) {
schooldet.pincode = value;
},
),
MyTextFormField(
hintText: 'State',
isEmail: true,
validator: (String value) {
if (value.isEmpty) {
return "Enter the state";
}
return null;
},
onSaved: (String value) {
schooldet.state = value;
},
),
RaisedButton(
color: Colors.blueAccent,
onPressed: () {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
widget.school.address = schooldet;
widget.onSaved(widget.school);
}
},
child:
Text('Next', style: TextStyle(color: Colors.white)))
]))));
}
}
form 3
class SchoolRegThree extends StatefulWidget {
School school;
final Function(School) onSaved;
SchoolRegThree({this.school, this.onSaved});
#override
_SchoolRegThreeState createState() => _SchoolRegThreeState();
}
class _SchoolRegThreeState extends State<SchoolRegThree> {
final _formKey = GlobalKey<FormState>();
SchoolUser schooluser;
#override
void initState() {
schooluser = widget.school.user;
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: new Form(
key: _formKey,
child: Column(children: <Widget>[
Container(
margin: EdgeInsets.only(top: 100),
child: MyTextFormField(
hintText: 'Username',
isPassword: true,
validator: (String value) {
if (value.length < 5) {
return 'Username should be at least 5 characters long';
}
_formKey.currentState.save();
return null;
},
onSaved: (String value) {
schooluser.username = value;
},
),
),
MyTextFormField(
hintText: 'New Password',
isPassword: true,
validator: (String value) {
if (value.length < 7) {
return 'Password should be at least 7 characters long';
} else if (schooluser.password != null) {
print(value);
print(schooluser.password);
}
return null;
},
onSaved: (String value) {
schooluser.password = value;
},
),
RaisedButton(
color: Colors.blueAccent,
onPressed: () {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
widget.school.user = schooluser;
widget.onSaved(widget.school);
}
},
child: Text('Done',
style: TextStyle(
color: Colors.white,
)))
]))));
}
}
and finally consolidate the model to a single model class
class School {
String schoolName;
String schoolPhone;
String schoolEmail;
String schoolWebsite;
SchoolDet address;
SchoolUser user;
}
class SchoolDet {
String addressOne;
String addressTwo;
String city;
String pincode;
String state;
}
class SchoolUser {
String username;
String password;
}
Best is to use a state management solution like flutter_bloc, provider, etc.
Store it in an array on a different file using state management.
Make the bloc/provider available to all the screens.
You can pass through constructor but I don't recommend that as it will be too messy.