Emit the data to parent Widget in Flutter
The point that you are missing is your setState
method call. You call the setState of the TestState2
.
For fixing that, there are two ways.
First way is to create a GlobalKey(https://docs.flutter.io/flutter/widgets/GlobalKey-class.html) and pass it as a parameter to the child widget.
And the second way is to create a global variable for the parent state and use it in the child state.
I modified the code below with the second approach.
_TestState _globalState = new _TestState();
class TestApp extends StatefulWidget {
@override
_TestState createState() => _globalState;
}
class _TestState extends State<TestApp>{
String abc = "";
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
body: new Column(
children: <Widget>[
new Text("This is text $abc"),
TestApp2()
],
),
),
);
}
}
class TestApp2 extends StatefulWidget {
TestApp2();
@override
_TestState2 createState() => new _TestState2();
}
class _TestState2 extends State<TestApp2>{
@override
Widget build(BuildContext context) {
return new Container(
width: 150.0,
height: 30.0,
margin: EdgeInsets.only(top: 50.0),
child: new FlatButton(
onPressed: (){
_globalState.setState((){
_globalState.abc = "Button clicked";
});
},
child: new Text("BUTTON"),
color: Colors.red,
),
);
}
}
In your example, a few assumptions were made. I will try to remove one by one.
You pass
abc
from parent to child and you mutated the child value on press on button. As primitive types are pass by value in dart, change in the value ofabc
in child will not change the value of parentabc
. Refer the below snippet.void main() { String abc = "oldValue"; changeIt(abc); print(abc); // oldValue } void changeIt(String abc) { abc = "newValue"; print(abc); //newValue }
Let's assume the first one is wrong(for understanding purpose). Then changing the value of
abc
in child will change the value ofabc
in parent. But without calling that insidesetState
of parent, parent will not reflect the change. In your case if you change the code as below, it will change the button text alone on click (as setState of child is called).new FlatButton( onPressed: () { setState( () { widget.abc = "RANDON TEXT"; }, ); }, child: new Text(widget.abc), // setting the text based on abc color: Colors.red, ),
Instead of using
globalState
which will be very difficult to maintain/debug as app grows, I would recommend usingcallbacks
. Please refer the below code.void main() => runApp(new TestApp()); class TestApp extends StatefulWidget { @override _TestState createState() => new _TestState(); } class _TestState extends State<TestApp> { String abc = "bb"; callback(newAbc) { setState(() { abc = newAbc; }); } @override Widget build(BuildContext context) { var column = new Column( children: <Widget>[ new Text("This is text $abc"), TestApp2(abc, callback) ], ); return new MaterialApp( home: new Scaffold( body: new Padding(padding: EdgeInsets.all(30.0), child: column), ), ); } } class TestApp2 extends StatefulWidget { String abc; Function(String) callback; TestApp2(this.abc, this.callback); @override _TestState2 createState() => new _TestState2(); } class _TestState2 extends State<TestApp2> { @override Widget build(BuildContext context) { return new Container( width: 150.0, height: 30.0, margin: EdgeInsets.only(top: 50.0), child: new FlatButton( onPressed: () { widget.callback("RANDON TEXT"); //call to parent }, child: new Text(widget.abc), color: Colors.red, ), ); } }
To write the very precise answer. Just use the call back like the above answer use this. So you want to call the state of ParentScreen from the another function/widget/class. Just follow this code
import 'package:showErrorMessage.dart';
class ParentScreen extends StatefulWidget {
ParentScreen({Key key}) : super(key: key);
@override
_ParentScreenState createState() => _ParentScreenState();
}
class _ParentScreenState extends State<ParentScreen> {
callback() {
setState(() {});
}
@override
Widget build(BuildContext context) {
String message = "hello";
return Container(
child: showErrorMessage(message, callback);,
);
}
}
And here is the child widget/function/class
import 'package:flutter/material.dart';
showErrorMessage(message, Function callback) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
message,
style: TextStyle(color: Colors.white, fontSize: 16),
),
GestureDetector(
onTap: () {
callback(); // ------ this will change/rebuild the state of its parent class
},
child: Icon(
Icons.refresh,
size: 30,
color: Colors.white,
)),
],
));
}