Reputation: 6292
I am stuck in my project where I have two stateful widgets created in flutter as two different dart files. Now, I have to access the instance of an object created in first widget in the second widget, but I am not so sure how I can do this in flutter when creating widgets.
One possible solution I thought of is to declare the two widgets in just one dart file instead of two dart files for two layouts, but I am curious if we can do it by declaring in two separate dart files.
I have posted the files just to re-create the issue.
main.dart
import 'package:flutter/material.dart';
import 'package:untitled2/models.dart';
import 'package:untitled2/secondwidget.dart';
void main() {
runApp(new MaterialApp(
home: new MyApp(),
),);
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
final TextEditingController _nameController = new TextEditingController();
final TextEditingController _emailIdController = new
TextEditingController();
final TextEditingController _passwordController = new
TextEditingController();
final TextEditingController _confirmPasswordController = new
TextEditingController();
MyModel myModel = new MyModel();
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
body: new ListView(
children: <Widget>[
new Container(
child: new TextFormField(
decoration: new InputDecoration(
labelText: 'Enter your Name'
),
controller: _nameController,
onSaved: (String value){myModel.name = value;} ,
),
),
new Container(
child: new TextFormField(
decoration: new InputDecoration(
labelText: 'EmailId'
),
controller: _emailIdController,
onSaved: (String value){myModel.emailId = value;}
),
),
new Container(
child: new TextFormField(
decoration: new InputDecoration(
labelText: 'Password'
),
controller: _passwordController,
onSaved: (String value){myModel.password = value;}
),
),
new Container(
child: new TextFormField(
decoration: new InputDecoration(
labelText: 'Confirm Password'
),
controller: _confirmPasswordController,
),
),
new Container(
child: new FlatButton(
onPressed: ((){
Navigator.push(context, new MaterialPageRoute(builder: (_) =>
new SecondScreen(),),);
}),
child: new Text('Save'),),
),
],
),
),
);
}
}
models.dart
class MyModel {
String name;
String emailId;
String password;
}
secondwidget.dart
import 'package:flutter/material.dart';
class SecondScreen extends StatefulWidget {
@override
_SecondScreenState createState() => new _SecondScreenState();
}
class _SecondScreenState extends State<SecondScreen> {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
body: new ListView(
children: <Widget>[
new Container(
child: new TextFormField(
decoration: new InputDecoration(
labelText: 'Enter address'
),
),
),
new Container(
child: new TextFormField(
decoration: new InputDecoration(
labelText: 'Address Line 2'
),
),
),
new Container(
child: new TextFormField(
decoration: new InputDecoration(
labelText: 'Address Line 3'
),
),
),
new Container(
child: new TextFormField(
decoration: new InputDecoration(
labelText: 'POST CODE'
),
),
),
new Container(
child: new TextFormField(
decoration: new InputDecoration(
labelText: 'Mobile Number'
),
),
),
new Container(
child: new FlatButton(
onPressed: ((){
//I want to push the data captured from main.dart and from
//secondwidget.dart into database
// I want to use the instance of MyModel from main.dart here to save
// the data captured from the first screen and this one into database
}),
child: new Text('Save'),),
),
],
),
),
);
}
}
Upvotes: 72
Views: 98329
Reputation: 116728
There are lots of ways to do this depending on your use case. Here are a few options:
State
. Then use the currentState
property of a GlobalKey
in one State
to get a reference to the other State
. Now you can access the created object via the public member. (Note: This pattern limits the testability and encapsulation of your State
, so use it sparingly.)InheritedWidget
that they use to look up the created object.ValueNotifier
. They can use this object to read and write the value.If you go into more detail on your use case we can help you pick a pattern that makes sense.
Here is some code implementing option #1.
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
final key = new GlobalKey<MyStatefulWidget1State>();
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
body: new Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
new MyStatefulWidget1(key: key),
new MyStatefulWidget2(),
],
),
),
);
}
}
class MyStatefulWidget1 extends StatefulWidget {
MyStatefulWidget1({ Key key }) : super(key: key);
State createState() => new MyStatefulWidget1State();
}
class MyStatefulWidget1State extends State<MyStatefulWidget1> {
String _createdObject = "Hello world!";
String get createdObject => _createdObject;
@override
Widget build(BuildContext context) {
return new Center(
child: new Text(_createdObject),
);
}
}
class MyStatefulWidget2 extends StatefulWidget {
State createState() => new MyStatefulWidget2State();
}
class MyStatefulWidget2State extends State<MyStatefulWidget2> {
String _text = 'PRESS ME';
@override
Widget build(BuildContext context) {
return new Center(
child: new RaisedButton(
child: new Text(_text),
onPressed: () {
setState(() {
_text = key.currentState.createdObject;
});
},
),
);
}
}
Upvotes: 97
Reputation: 1462
Here is how I pass parameter to the child widget.
First Widget dart file
class FirstWidget extends StatefulWidget {
_FirstWidgetState createState() => _FirstWidgetState()
}
class _FirstWidgetState extends State<FirstWidget> {
String param = "My parameter";
@override
Widget build(BuildContext context) {
return Container(
child:
SecondWidget(param), //pass parmater here
);
}
}
Second Widget dart file
class SecondWidget extends StatefulWidget {
final String param;
SecondWidget(this.param); //passed paramter
_SecondWidgetState createState() => _SecondWidgetState()
}
class _SecondWidgetState extends State<SecondWidget> {
@override
Widget build(BuildContext context) {
return Container(
child:
Text(widget.param), //output paramter
);
}
}
Upvotes: 9
Reputation: 613
You can pass the model when you construct SecondScreen
widget.
Add model to SecondScreen
constructor:
class SecondScreen extends StatefulWidget {
final MyModel myModel;
SecondScreen(MyModel myModel, {Key key}):
super(key: key);
...
}
Pass model when you construct SecondScreen
in main.dart
Navigator.push(context, new MaterialPageRoute(builder: (_) =>
new SecondScreen(model)));
Now you can access model in _SecondScreenState
via widget.myModel
Upvotes: 14