flutter child props is changing parent variable - flutter

I send a variable from a parent widget to its child. by parameters. I'm using that variable on the parent and child widget. for example, I'm using variable.name on the parent widget. When I change the variable on the child widget widget.variable.name = 'all' it's also updating the parent widget but I just wanna change that on the child widget.

You can make a temporary variable inside child state.
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
int parentVal = 1;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
ElevatedButton(
onPressed: () {
setState(() {
parentVal++;
});
},
child: Text("parent val: $parentVal"),
),
ChildW(
childval: parentVal,
)
],
));
}
}
class ChildW extends StatefulWidget {
final int childval;
const ChildW({
Key? key,
required this.childval,
}) : super(key: key);
#override
State<ChildW> createState() => _ChildWState();
}
class _ChildWState extends State<ChildW> {
late int tempChildVal;
#override
void initState() {
super.initState();
tempChildVal = widget.childval;
}
#override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () {
setState(() {
tempChildVal++;
});
},
child: Text("child val: $tempChildVal"),
);
}
}

Related

Prevent children from rebuilding in SliverList

Minimum example:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
body: CustomScrollView(
slivers: [Example()],
),
));
}
}
class Example extends StatefulWidget {
const Example({Key? key}) : super(key: key);
#override
State<Example> createState() => ExampleState();
}
class ExampleState extends State<Example> with AutomaticKeepAliveClientMixin {
#override
Widget build(BuildContext context) {
super.build(context);
return SliverList(
delegate: SliverChildListDelegate(const <Widget>[
SizedBox(
height: 1400,
),
CheckboxWidget()
], addAutomaticKeepAlives: true));
}
#override
bool get wantKeepAlive => true;
}
class CheckboxWidget extends StatefulWidget {
const CheckboxWidget({Key? key}) : super(key: key);
#override
State<CheckboxWidget> createState() => _CheckboxWidgetState();
}
class _CheckboxWidgetState extends State<CheckboxWidget> {
late bool _personalData = false;
#override
Widget build(BuildContext context) {
return Checkbox(
checkColor: Colors.black,
onChanged: (bool? value) {
setState(() {
_personalData = value!;
});
},
value: _personalData,
);
}
}
If you click the checkbox, then scroll out of view and then back in to view.. The box becomes unchecked. This is because the widget rebuilds...setting the _personalData to false. I would of thought addAutomaticKeepAlives would prevent the widget rebuilding and keep the state of the checkbox. How do I prevent CheckboxWidget from rebuilding?
Firstly, I will choose state management or passing value to the CheckboxWidget. To answer this question, we need to save (keep alive) the state of CheckboxWidget. Therefore, we need to use AutomaticKeepAliveClientMixin on _CheckboxWidgetState instead of parent widget.
class CheckboxWidget extends StatefulWidget {
const CheckboxWidget({Key? key}) : super(key: key);
#override
State<CheckboxWidget> createState() => _CheckboxWidgetState();
}
class _CheckboxWidgetState extends State<CheckboxWidget>
with AutomaticKeepAliveClientMixin {
late bool _personalData = false;
#override
Widget build(BuildContext context) {
super.build(context);
return Checkbox(
checkColor: Colors.black,
onChanged: (bool? value) {
setState(() {
_personalData = value!;
});
},
value: _personalData,
);
}
#override
bool get wantKeepAlive => true;
}
class Example extends StatefulWidget {
const Example({Key? key}) : super(key: key);
#override
State<Example> createState() => ExampleState();
}
class ExampleState extends State<Example> {
#override
Widget build(BuildContext context) {
return SliverList(
delegate: SliverChildListDelegate(
const <Widget>[
SizedBox(
height: 1400,
),
CheckboxWidget()
],
),
);
}
}

Call Navigator from outside state or call child state method from parent

I ended up with a parent calling a child method, which is fine, but I can't call Navigator outside the state class. My goal is either to move the child method in it's state and somehow access it, or to call Navigator form outside the state in a Stateful widget.
What is the best approach to this problem?
import 'package:flutter/material.dart';
class ParentClass extends StatefulWidget {
const ParentClass({Key? key}) : super(key: key);
#override
_ParentClassState createState() => _ParentClassState();
}
class _ParentClassState extends State<ParentClass> {
ChildClass childclass = ChildClass();
#override
Widget build(BuildContext context) {
return Container(
child: ElevatedButton(
child: Text('Button'),
onPressed: () => {
childclass.callNavigator(),//or call callNavigatorState
}),
);
}
}
class ChildClass extends StatefulWidget {
const ChildClass({Key? key}) : super(key: key);
void callNavigator() {
//call navigator from here
}
#override
_ChildClassState createState() => _ChildClassState();
}
class _ChildClassState extends State<ChildClass> {
void callNavigatorState(){
//access from parent widget?
}
#override
Widget build(BuildContext context) {
return Container();
}
}
you can access a stateful's state, using Globalkey.currentState...
check this sample code:
class MyHomePage extends StatelessWidget {
MyHomePage({Key? key}) : super(key: key);
final child = ChildWidget(key: GlobalKey());
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
child,
ElevatedButton(
onPressed: () {
(((child as ChildWidget).key as GlobalKey).currentState!
as _ChildWidgetState)
.someFunction();
},
child: Text("childWidget someFunction"))
],
),
);
}
}
class ChildWidget extends StatefulWidget {
const ChildWidget({Key? key}) : super(key: key);
#override
_ChildWidgetState createState() => _ChildWidgetState();
}
class _ChildWidgetState extends State<ChildWidget> {
void someFunction() {
print("childWidget someFunction");
}
#override
Widget build(BuildContext context) {
return Container();
}
}

Event Listeners in flutter

Is there a way I can listen to a button click in flutter? I want to know if the button is clicked in another class that creates a object of that button.
What i want to do is let MyButtonRow know when MyButton is clicked, since it involves changing variables in MyButtonRow.
The functionality i am looking for is similar to .setEventListener in JavaScript
So here's the code
class MyButtonRow extends StatefulWidget {
const MyButtonRow({Key? key}) : super(key: key);
#override
_MyButtonRowState createState() => _MyButtonRowState();
}
class _MyButtonRowState extends State<MyButtonRow> {
#override
Widget build(BuildContext context) {
return Container(width: MediaQuery.of(context).size.width,
child: Row(children: <Widget>[MyButtonTile()],));
}
}
class MyButtonTile extends StatefulWidget {
const MyButtonTile({Key? key}) : super(key: key);
#override
_MyButtonTileState createState() => _MyButtonTileState();
}
class _MyButtonTileState extends State<MyButtonTile> {
#override
Widget build(BuildContext context) {
return TextButton(onPressed: (){
//notify MyButtonRow about the click
}, child: Text("hello"));
}
}
Firstly you declare onTap function on your child widget and then just pass the onTap function from where you define the MyButtonTile
class MyButtonRow extends StatefulWidget {
const MyButtonRow({Key? key}) : super(key: key);
#override
_MyButtonRowState createState() => _MyButtonRowState();
}
class _MyButtonRowState extends State<MyButtonRow> {
#override
Widget build(BuildContext context) {
return Container(width: MediaQuery.of(context).size.width,
child: Row(children: <Widget>[MyButtonTile(onTap: (){
print("Notify me");
})],));
}
}
class MyButtonTile extends StatelessWidget {
final Function onTap;
MyButtonTile({this.onTap});
#override
Widget build(BuildContext context) {
return TextButton(onPressed:onTap,//notify MyButtonRow about the click
child: Text("hello"));
}
}

Flutter: How to set state of parent widget

I'd like to change the color of a parent container with a button from a child widget.
Let's say I have a parentClass widget and a childClass widget. The container with dynamic color is in parentClass, and the button is in childClass. At first the container is blue and I want to make it red on button tap.
Color dynamicColor;
class ParentClass extends StatefulWidget {
ParentClass({Key key}) : super(key: key);
#override
_ParentClassState createState() => _ParentClassState();
}
class _ParentClassState extends State<ParentClass> {
#override
void initState() {
super.initState();
setState(() {
dynamicColor = Colors.blue;
});
}
#override
Widget build(BuildContext context) {
return Column(
children: [
ChildClass(),
Container(
color: dynamicColor,
child: ...
)
],
);
}
}
class ChildClass extends StatefulWidget {
ChildClass({Key key}) : super(key: key);
#override
_ChildClassState createState() => _ChildClassState();
}
class _ChildClassState extends State<ChildClass> {
#override
Widget build(BuildContext context) {
return Container(
child: TextButton(
onPressed: () {
setState(() {
dynamicColor = Colors.red; // What I want to do
});
},
child: Text('Change parent container color'),
),
);
}
}
You can create a function on parent widget and pass to child with parameter.
Like:
void delete() async {
setState(() {
dynamicColor = Colors.blue;
});
}
on your Widget Tree
CustomChild(function: () => delete()),
Your custom Widget
class CustomChild extends StatelessWidget {
Function function;
CustomChild({this.function})
#override
Widget build(BuildContext context) {
return Container();
}
}

How to Set/Update State of StatefulWidget from other StatefulWidget in stack Flutter?

am using something like that
class OpenPage extends StatefulWidget {
#override
_OpenPageState createState() => _OpenPageState();
}
class _OpenPageState extends State<OpenPage> {
int id= 0;
}
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
classOne(), //id changed here
classTwo(), //here data depends on id
],
);
}
where classOne and classTwo are StatefulWidget .
what am tring to do when i change id value in classOne i want it to change the classTwo where the data in the classTwo depends on the id that change in classOne .
how could i setState classTwo when the id in classOne change ?
You could pass the function of manipulating the id as an argument of WidgetOne. In this example WidgetOne and WidgetTwo are StatelessWidget but it should also work for StatelessWidget
class OpenPage extends StatefulWidget {
#override
_OpenPage createState() => _OpenPage();
}
class _OpenPage extends State<OpenPage > {
int id = 0;
#override
Widget build(BuildContext context) {
return Stack(
children: [
WidgetOne(
onPressed: () {
setState(() {
id++;
});
},
),
WidgetTwo(
id: id,
),
],
);
}
}
class WidgetOne extends StatelessWidget {
final VoidCallback onPressed;
const WidgetOne({Key key, this.onPressed}) : super(key: key);
#override
Widget build(BuildContext context) {
return IconButton(
icon: Icon(Icons.add),
onPressed: onPressed,
);
}
}
class WidgetTwo extends StatelessWidget {
final int id;
const WidgetTwo({Key key, this.id}) : super(key: key);
#override
Widget build(BuildContext context) {
return Text(id.toString());
}
}