How to pass data to a widget inside of another widget - flutter

I was able to pass the data widget.value from the FirstPage to SecondPage. There's a widget called thirdWidget inside SecondPage.
How do I pass widget.value to thirdWidget?
class FirstPage extends StatefulWidget {
#override
State<StatefulWidget> createState() => FirstPageState();
}
class FirstPageState extends State< FirstPage > {
final myController = TextEditingController();
#override
void dispose() {
myController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Route'),
),
body: Column(
children: <Widget>[
TextField(
controller: myController,
decoration: new InputDecoration(labelText: "Enter a number"),
keyboardType: TextInputType.number,
),
RaisedButton(
child: Text("show text"),
onPressed: () {
return Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ThirdRoute(
selectedDate: selectedDate,
value: myController.text,
)),
);
},
);
},
),
],
),
);
}
}
class SecondPage extends StatefulWidget {
final String value;
ThirdRoute({Key key, this.value})
: super(key: key);
#override
SecodpageState createState() => SecodpageState();
}
class SecodpageState extends State< SecondPage > {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Calendar Page"),
),
body: Column(
children: <Widget>[
Text("${widget.value}"),
Row(
children: thirdWidget(),
),
Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
],
),
);
}
}
List<Widget> thirdWidget() {
return Text("${widget.value}”)
}

Use this in your SecondPage
Row(
children: thirdWidget(widget.value),
)
And update your thirdWidget like:
List<Widget> thirdWidget(var data) {
// data is widget.value
return [];
}

Just pass that info into the state class. Something like that:
class SecondPage extends StatefulWidget {
final String value;
ThirdRoute({Key key, this.value})
: super(key: key);
#override
SecodpageState createState() => SecodpageState(value);
}
class SecodpageState extends State< SecondPage > {
final String value;
SecodpageState(this.value);
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Calendar Page"),
),
body: Column(
children: <Widget>[
Text("${widget.value}"),
Row(
children: thirdWidget(),
),
Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
],
),
);
}
}
List<Widget> thirdWidget() {
return Text(value);
}

Related

why setState not working for List of widgets in flutter

I am new in flutter I try to experiment with List of Widget . I try to change state inside the list of widget i.e. initialized in initState . I create sample example to what I want to achieve.
class Testing extends StatefulWidget {
const Testing({super.key});
#override
State<Testing> createState() => _TestingState();
}
class _TestingState extends State<Testing> {
bool isChanged = false;
List<Widget> simpleWidget = [];
#override
void initState() {
simpleWidget = [_someComplexWidget(), _someComplexWidget()];
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title:const Text("Test"),
),
body: Center(
child: Column(
children: [
Container(
child: Column(
children: simpleWidget,
),
),
ElevatedButton(
onPressed: () {
setState(() {
isChanged = !isChanged;
});
},
child: const Text("Click"))
],
),
),
);
}
Widget _someComplexWidget() {
return Text(
"Hello",
style: TextStyle(color: isChanged ? Colors.red : Colors.blue),
);
}
}
I also try with keys but it did not work in this sample code. When to Use Keys
What is the reason behind not working this code.
Because your simpleWidget is created at initState & it will not change on rebuild.
You should add [_someComplexWidget(), _someComplexWidget()] under build for it to change dynamically based on the current state.
class Testing extends StatefulWidget {
const Testing({super.key});
#override
State<Testing> createState() => _TestingState();
}
class _TestingState extends State<Testing> {
bool isChanged = false;
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Test"),
),
body: Center(
child: Column(
children: [
Container(
child: Column(
children: [_someComplexWidget(), _someComplexWidget()], // HERE
),
),
ElevatedButton(
onPressed: () {
setState(() {
isChanged = !isChanged;
});
print(isChanged);
},
child: const Text("Click"))
],
),
),
);
}
Widget _someComplexWidget() {
return Text(
"Hello",
style: TextStyle(color: isChanged ? Colors.red : Colors.blue),
);
}
}

How to show selected checkbox on prev screen?

I need to display checkboxes selected by the user on the previous page using pop()
I have a function that displays the user's message on the previous page and I need to pass the selected checkboxes in the same way. How to pass them as arguments to pop()?
Screen with checkboxes:
const TextScreen({Key? key}) : super(key: key);
#override
State<TextScreen> createState() => _TextScreenState();
}
class _TextScreenState extends State<TextScreen> {
// initial values for checkboxes
bool _privacy = false;
bool _termsOfUse = false;
// text controller for message input
TextEditingController textController = TextEditingController();
#override
void dispose() {
textController.dispose();
super.dispose();
}
// go to result screen
void getResult(BuildContext context) {
String valueResult = textController.text;
Navigator.pop(context, valueResult);
}
#override
Widget build(BuildContext context) {
//change state for privacy checkbox
_onPrivacyChange(value) {
setState(() {
_privacy = value!;
});
}
//change state for terms of use checkbox
_onTermsOfUSeChange(value) {
setState(() {
_termsOfUse = value!;
});
}
return Scaffold(
appBar: AppBar(
title: const Text('Enter data'),
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
controller: textController,
decoration: const InputDecoration(labelText: 'Message')),
const SizedBox(height: 20),
CheckboxListTile(
title: const Text('Privacy'),
controlAffinity: ListTileControlAffinity.leading,
value: _privacy,
onChanged: _onPrivacyChange,
contentPadding: EdgeInsets.zero,
),
CheckboxListTile(
title: const Text('Terms of use'),
controlAffinity: ListTileControlAffinity.leading,
value: _termsOfUse,
onChanged: _onTermsOfUSeChange,
contentPadding: EdgeInsets.zero,
),
ElevatedButton(
onPressed: () {
getResult(context);
},
child: const Text('Display result'))
],
)),
);
}
}
Screen with results display:
class ResultScreen extends StatefulWidget {
const ResultScreen({Key? key}) : super(key: key);
#override
State<ResultScreen> createState() => _ResultScreenState();
}
class _ResultScreenState extends State<ResultScreen> {
String? _valueText = '';
#override
Widget build(BuildContext context) {
// navigation to next screen
void _navToNextScreen(BuildContext context) async {
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => const TextScreen()),
);
// update widget after result comes back
setState(() {
_valueText = result;
});
}
return Scaffold(
appBar: AppBar(
title: const Text('Results'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
_navToNextScreen(context);
},
child: const Text('Enter data'),
),
const SizedBox(height: 50),
Text('Message: $_valueText'),
const SizedBox(height: 20),
Text('Checkboxes: '),
],
)),
);
}
}
I think this should be the job of a simple state management strategy; for communication between separate widgets (in this case, two page widgets), that's the cleanest approach. You should create a common service to which both page widgets are subscribed: one to trigger the changes, the other to capture them and display them, using a ChangeNotifier service along with Consumer widgets, as shown below:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(
ChangeNotifierProvider(
create: (_) => SelectedData(),
child: MyApp()
)
);
}
class SelectedData extends ChangeNotifier {
bool _privacy = false;
bool _termsOfUse = false;
String _valueResult = '';
bool get privacy => _privacy;
bool get termsOfUse => _termsOfUse;
String get valueResult => _valueResult;
set privacy(bool value) {
_privacy = value;
notifyListeners();
}
set termsOfUse(bool value) {
_termsOfUse = value;
notifyListeners();
}
set valueResult(String value) {
_valueResult = value;
notifyListeners();
}
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: ResultScreen(),
),
),
);
}
}
class TextScreen extends StatefulWidget {
const TextScreen({Key? key}) : super(key: key);
#override
State<TextScreen> createState() => _TextScreenState();
}
class _TextScreenState extends State<TextScreen> {
// text controller for message input
TextEditingController textController = TextEditingController();
#override
void initState() {
super.initState();
}
#override
void dispose() {
textController.dispose();
super.dispose();
}
// go to result screen
void getResult(BuildContext context) {
Navigator.pop(context);
}
#override
Widget build(BuildContext context) {
SelectedData data = Provider.of<SelectedData>(context, listen: false);
textController.text = data.valueResult;
//change state for privacy checkbox
_onPrivacyChange(value) {
data.privacy = value;
}
//change state for terms of use checkbox
_onTermsOfUSeChange(value) {
data.termsOfUse = value;
}
return Scaffold(
appBar: AppBar(
title: const Text('Enter data'),
),
body: Consumer<SelectedData>(
builder: (context, selectedData, child) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
controller: textController,
onChanged: (value) {
data.valueResult = value;
},
decoration: const InputDecoration(labelText: 'Message')),
const SizedBox(height: 20),
CheckboxListTile(
title: const Text('Privacy'),
controlAffinity: ListTileControlAffinity.leading,
value: selectedData.privacy,
onChanged: _onPrivacyChange,
contentPadding: EdgeInsets.zero,
),
CheckboxListTile(
title: const Text('Terms of use'),
controlAffinity: ListTileControlAffinity.leading,
value: selectedData.termsOfUse,
onChanged: _onTermsOfUSeChange,
contentPadding: EdgeInsets.zero,
),
ElevatedButton(
onPressed: () {
getResult(context);
},
child: const Text('Display result'))
],
));
}
),
);
}
}
class ResultScreen extends StatefulWidget {
const ResultScreen({Key? key}) : super(key: key);
#override
State<ResultScreen> createState() => _ResultScreenState();
}
class _ResultScreenState extends State<ResultScreen> {
#override
Widget build(BuildContext context) {
// navigation to next screen
void _navToNextScreen(BuildContext context) async {
await Navigator.push(
context,
MaterialPageRoute(builder: (context) => const TextScreen()),
);
}
return Scaffold(
appBar: AppBar(
title: const Text('Results'),
),
body: Consumer<SelectedData>(
builder: (context, selectedData, child) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
_navToNextScreen(context);
},
child: const Text('Enter data'),
),
const SizedBox(height: 50),
Text('Message: ${selectedData.valueResult}'),
const SizedBox(height: 20),
const Text('Checkboxes: '),
Text('Privacy: ${selectedData.privacy}'),
Text('Terms of Use: ${selectedData.termsOfUse}')
],
));
}
),
);
}
}
Here's the output when you implement it this way:
So from what i see is you are only passing one value that is message and you what many values to pass at a time so here the map can be used and as pop() function takes dynamic returns you can pass any thing.
From your example i have created a sample example that will be a working proof which will demostrate the using map for passing data to previous screen.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: ResultScreen(),
);
}
}
class TextScreen extends StatefulWidget {
const TextScreen({Key? key}) : super(key: key);
#override
_TextScreenState createState() => _TextScreenState();
}
class _TextScreenState extends State<TextScreen> {
// initial values for checkboxes
bool _privacy = false;
bool _termsOfUse = false;
// text controller for message input
TextEditingController textController = TextEditingController();
#override
void dispose() {
textController.dispose();
super.dispose();
}
// go to result screen
void getResult(BuildContext context) {
String valueResult = textController.text;
final data = {
"message":valueResult,
"privacy": _privacy,
'terms':_termsOfUse,
};
Navigator.pop(context, data);
}
#override
Widget build(BuildContext context) {
//change state for privacy checkbox
_onPrivacyChange(value) {
setState(() {
_privacy = value!;
});
}
//change state for terms of use checkbox
_onTermsOfUSeChange(value) {
setState(() {
_termsOfUse = value!;
});
}
return Scaffold(
appBar: AppBar(
title: const Text('Enter data'),
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
controller: textController,
decoration: const InputDecoration(labelText: 'Message')),
const SizedBox(height: 20),
CheckboxListTile(
title: const Text('Privacy'),
controlAffinity: ListTileControlAffinity.leading,
value: _privacy,
onChanged: _onPrivacyChange,
contentPadding: EdgeInsets.zero,
),
CheckboxListTile(
title: const Text('Terms of use'),
controlAffinity: ListTileControlAffinity.leading,
value: _termsOfUse,
onChanged: _onTermsOfUSeChange,
contentPadding: EdgeInsets.zero,
),
ElevatedButton(
onPressed: () {
getResult(context);
},
child: const Text('Display result'))
],
)),
);
}
}
class ResultScreen extends StatefulWidget {
const ResultScreen({Key? key}) : super(key: key);
#override
State<ResultScreen> createState() => _ResultScreenState();
}
class _ResultScreenState extends State<ResultScreen> {
String? _valueText = '';
bool _privacyValue =false;
bool _termsOfUse = false;
#override
Widget build(BuildContext context) {
// navigation to next screen
void _navToNextScreen(BuildContext context) async {
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => const TextScreen()),
);
if(result !=null)
{
setState(() {
if(result['message']!=null )_valueText = result['message'];
if(result['privacy']!=null) _privacyValue = result['privacy'];
if(result['terms']!=null) _termsOfUse = result['terms'];
});
}
}
return Scaffold(
appBar: AppBar(
title: const Text('Results'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
_navToNextScreen(context);
},
child: const Text('Enter data'),
),
const SizedBox(height: 50),
Text('Message: $_valueText'),
const SizedBox(height: 20),
Text('Privacy Value: $_privacyValue '),
const SizedBox(height: 20),
Text('Terms Value: $_termsOfUse '),
],
)),
);
}
}
You can make changes as per your needs, So let me know if it works.

How to validate and send the data to another page in flutter

I am a newbie to flutter
and i would to like to create simple input data and pass the data to other page and show the text.
here is my code
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
const appTitle = 'Form Validation Demo';
return MaterialApp(
title: appTitle,
home: Scaffold(
appBar: AppBar(
title: const Text(appTitle),
),
body: const MyForm(),
),
);
}
}
class MyForm extends StatefulWidget {
const MyForm({Key? key}) : super(key: key);
#override
MyFormState createState() {
return MyFormState();
}
}
class MyFormState extends State<MyForm> {
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Page2(_formKey)),
);
}
},
child: const Text('Submit'),
),
],
),
);
}
}
class Page2 extends StatelessWidget {
Page2(final data){
this.data = data;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Page 2'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(this.data),
RaisedButton(
child: Text('BACK'),
onPressed: () {
Navigator.pop(context);
},
),
],
),
),
);
}
}
But finally, it gets
The setter 'data' isn't defined for the type 'Page2'.
error
Any idea how to do it??
and what's wrong with my code
Thank you very much.
You can make a global variable and easily use it on other screen. all you need is updating some of your code to the following
final _formKey = GlobalKey<FormState>();
TextEditingController inputController = TextEditingController();
String result;
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
const appTitle = 'Form Validation Demo';
return MaterialApp(
title: appTitle,
home: Scaffold(
appBar: AppBar(
title: const Text(appTitle),
),
body: const MyForm(),
),
);
}
}
class MyForm extends StatefulWidget {
const MyForm({Key? key}) : super(key: key);
#override
MyFormState createState() {
return MyFormState();
}
}
class MyFormState extends State<MyForm> {
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
controller: inputController,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState.validate()) {
setState(() {
result = inputController.text;
});
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Page2()),
);
}
},
child: const Text('Submit'),
),
],
),
),
),
);
}
}
class Page2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Page 2'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(result),
RaisedButton(
child: Text('BACK'),
onPressed: () {
Navigator.pop(context);
},
),
],
),
),
);
}
}
You should define data in Page2, something like this :
class Page2 extends StatelessWidget {
final data = GlobalKey<FormState>();
Page2(final data){
this.data = data;
}
See Send data to a new screen in the Flutter cookbook.

Flutter for web routing with multiple material apps

I have an issue regarding the routing of the flutter for the web. For specific reasons in my project, I have multiple material apps. So the platform that I'm building is a material app, let's name it 'Parent'. In this material app at some point lower in the widget tree I have a child that is also a material app let's name it 'Child'. When the user arrives at the point in the Parent tree where Child is rendered, it looks like the routing of Parent is replaced with the actual routing of Child. Is there any way to prevent this from happening?
Since I can't share the actual code I've recreated a minimal example:
import 'package:flutter/material.dart';
void main() {
runApp(ParentApp());
}
class ParentApp extends StatefulWidget {
#override
_ParentAppState createState() => _ParentAppState();
}
class _ParentAppState extends State<ParentApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Parent',
initialRoute: '/parent-home',
routes: {
'/parent-home': (context) => ParentHome(),
'/parent-second': (context) => ParentSecondRoute(),
},
);
}
}
class ParentHome extends StatefulWidget {
#override
_ParentHomeState createState() => _ParentHomeState();
}
class _ParentHomeState extends State<ParentHome> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey,
body: Container(
child: Center(
child: RaisedButton(
child: Text('Go to second route'),
onPressed: () => Navigator.pushNamed(
context,
'/parent-second',
),
),
),
),
);
}
}
class ParentSecondRoute extends StatefulWidget {
#override
_ParentSecondRouteState createState() => _ParentSecondRouteState();
}
class _ParentSecondRouteState extends State<ParentSecondRoute> {
bool isChildRendered;
#override
void initState() {
isChildRendered = false;
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Flexible(
child: isChildRendered
? ChildApp()
: Container(
color: Colors.green,
child: Center(
child: RaisedButton(
child: Text('Go to home'),
onPressed: () => Navigator.of(context).pop(),
),
),
),
),
Flexible(
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Checkbox(
value: isChildRendered,
onChanged: (value) => setState(() {
isChildRendered = value;
}),
),
SizedBox(width: 5),
Text('Is child rendered?'),
],
),
),
)
],
),
);
}
}
class ChildApp extends StatefulWidget {
#override
_ChildAppState createState() => _ChildAppState();
}
class _ChildAppState extends State<ChildApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Child',
initialRoute: '/child-route-i-don\'t-want-to-see',
routes: {
'/child-route-i-don\'t-want-to-see': (context) => Container(
color: Colors.brown,
),
},
);
}
}
Solution with ModalRoute Class
You can solve it this way, by using the ModalRoute Class and passing the current route name defined in its settings as parameter to the Child:
ChildApp(ModalRoute.of(context).settings.name)
class ChildApp extends StatefulWidget {
final String route;
const ChildApp(this.route);
#override
_ChildAppState createState() => _ChildAppState();
}
class _ChildAppState extends State<ChildApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Child',
initialRoute: widget.route,
routes: {
widget.route: (context) => Container(
color: Colors.brown,
),
},
);
}
}
name → String?
The name of the route (e.g., "/settings"). [...]
Full example below:
import 'package:flutter/material.dart';
void main() {
runApp(ParentApp());
}
class ParentApp extends StatefulWidget {
#override
_ParentAppState createState() => _ParentAppState();
}
class _ParentAppState extends State<ParentApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Parent',
initialRoute: '/parent-home',
routes: {
'/parent-home': (context) => ParentHome(),
'/parent-second': (context) => ParentSecondRoute(),
},
);
}
}
class ParentHome extends StatefulWidget {
#override
_ParentHomeState createState() => _ParentHomeState();
}
class _ParentHomeState extends State<ParentHome> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey,
body: Container(
child: Center(
child: RaisedButton(
child: Text('Go to second route'),
onPressed: () => Navigator.pushNamed(
context,
'/parent-second',
),
),
),
),
);
}
}
class ParentSecondRoute extends StatefulWidget {
#override
_ParentSecondRouteState createState() => _ParentSecondRouteState();
}
class _ParentSecondRouteState extends State<ParentSecondRoute> {
bool isChildRendered;
#override
void initState() {
isChildRendered = false;
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Flexible(
child: isChildRendered
? ChildApp(ModalRoute.of(context).settings.name) // this line
: Container(
color: Colors.green,
child: Center(
child: RaisedButton(
child: Text('Go to home'),
onPressed: () => Navigator.of(context).pop(),
),
),
),
),
Flexible(
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Checkbox(
value: isChildRendered,
onChanged: (value) => setState(() {
isChildRendered = value;
}),
),
SizedBox(width: 5),
Text('Is child rendered?'),
],
),
),
)
],
),
);
}
}
class ChildApp extends StatefulWidget {
final String route;
const ChildApp(this.route); // and this one
#override
_ChildAppState createState() => _ChildAppState();
}
class _ChildAppState extends State<ChildApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Child',
initialRoute: widget.route,
routes: {
widget.route: (context) => Container(
color: Colors.brown,
),
},
);
}
}
Home
Second Route

Flutter setState public var to another page?

how to setState public var to another page?
int x = 1;
that was in public
in the first page text(x) i want to setstate from the other page
my first page is
class AddFullRequest extends StatefulWidget {
#override
_AddFullRequestState createState() => _AddFullRequestState();
}
class _AddFullRequestState extends State<AddFullRequest> {
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Text(x),
GestureDetector(
onTap: (){
Navigator.of(context).push(new MaterialPageRoute(
builder: (BuildContext context) => AddItemScr()));
},
child: Text('goto'),
),
],
),
);
}
in the other page button to ++ the var in the first page
my other page is
class AddItemScr extends StatefulWidget {
#override
_AddItemScrState createState() => _AddItemScrState();
}
class _AddItemScrState extends State<AddItemScr> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: WillPopScope(onWillPop: (){
Navigator.of(context).pop();
},
child: Column(
children: <Widget>[
FlatButton(onPressed: (){setState(() {
x++;
});}, child: Text('pluss'),)
],
),
),
);
}
}
please help me with this
You can use the callback pattern. In this example, a function (onPressed) is passed to the child. The child calls the function when a button is pressed:
class AddFullRequest extends StatefulWidget {
#override
_AddFullRequestState createState() => _AddFullRequestState();
}
class _AddFullRequestState extends State<AddFullRequest> {
int _x = 0;
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Text("$_x"),
GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => AddItemScr(
onPressed: () => setState(() => _x++),
),
),
);
},
child: Text('goto'),
),
],
),
);
}
}
class AddItemScr extends StatelessWidget {
final VoidCallback onPressed;
const AddItemScr({
Key key,
#required this.onPressed,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
FlatButton(
onPressed: onPressed,
child: Text('Increment'),
),
],
),
);
}
}
You can pass variables between screens. NavigatorState#pop supports passing objects that you can await in the previous screen and set it to it's value.
class AddFullRequest extends StatefulWidget {
#override
_AddFullRequestState createState() => _AddFullRequestState();
}
class _AddFullRequestState extends State<AddFullRequest> {
int x = 0;
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Text('$x'),
GestureDetector(
onTap: () async {
final result = await Navigator.of(context).push<int>(
MaterialPageRoute(
builder: (_) => AddItemScr(variable: x),
),
);
x = result;
setState(() {});
},
child: Text('goto'),
),
],
),
);
}
}
class AddItemScr extends StatefulWidget {
final int variable;
AddItemScr({this.variable});
#override
_AddItemScrState createState() => _AddItemScrState();
}
class _AddItemScrState extends State<AddItemScr> {
int _variable;
#override
void initState() {
_variable = widget.variable;
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
FlatButton(
onPressed: () {
setState(() {
_variable++;
});
},
child: Text('pluss'),
),
FlatButton(
onPressed: () {
Navigator.of(context).pop(_variable);
},
child: Text('go back'),
),
],
),
);
}
}