How to change only 1 Child Widget from a Parent Widget in Flutter

I have the Problem, that I want to update only 1 Child Widget from a Parent Widget and not all of the Child Widgets.

This Code is written specificly for the Web so it should work there, every other System like Android or ... is not important.

So lets say I have as Parent a Screen with a Grid. Inside of this Grid is in every single Field a Widget. Now these Widgets are all from the same kind (every Field is from a class Field which defines how it looks and so on). These Fields are Stateful so they can change their Properties. Now I want to call from the Parent only one of the available Fields and update this Field. I dont want to update all of the Fields.

As Example: This is my Grid and every single Field is a Widget.

The complete Grid with every Field is inside another Widget (the Parent one).

_|_|_|_|_|_|_
_|_|_|_|_|_|_
_|_|_|_|_|_|_
 | | | | | |

Now I want to update the Field which is marked with an x.

_|_|_|_|_|_|_
_|_|_|_|x|_|_
_|_|_|_|_|_|_
 | | | | | |

If I make my Parent Widget Stateful and call setstate all of the widgets get updated and not the single one i am trying to update.

x|x|x|x|x|x|x
x|x|x|x|x|x|x
x|x|x|x|x|x|x
x|x|x|x|x|x|x

So it looks like this (all of them get updated).

Another Way I tried was to define a Function inside the Child Widget which gets called from the Parent Widget, but there was a Problem. It only worked directly after I started the Program. If I reloaded or added a print line and then reloaded its not working anymore.

I have tried different other Things not relating to the Problem so dont be surprised if my code looks a little bit weird. It is just for testing. The Parent Widget would preferably be a Stateless one but if it only works with Stateful its just fine. You can change everything in my Code if this helps my Problem.

Thanks for your help :)

This is my Parent Class: it should keep track of all Widgets inside the Grid but because of testing there is currently no Grid just a few Fields which I want to update with the first OutlinedButton. The second OutlinedButton reloads everything.

class Game extends StatefulWidget {
  _GameState createState() => _GameState();
}

class _GameState extends State<Game> {
  @override
  Widget build(BuildContext context) {
    Field field = new Field(
      text: "Button 3",
    );

    print("Build Parent");
    return Container(
      color: Colors.grey,
      child: Center(
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            Field(
              text: "Button 1",
              callback: () {
                print("Parent: Callback Button 1");
              },
            ),
            OutlinedButton(
              onPressed: () {
                print("Parent: changeIcon Button 3");

                if (field.changeIcon == null) {
                  print("rly");
                } else {
                  field.changeIcon(Icons.save);
                }
              },
              child: Text("Change Button 3"),
            ),
            Field(
              text: "Button 2",
              func: (int num) {
                print("Parent: Number Button 2: " + num.toString());

                return "worked!";
              },
              returnValue: () {
                return "Dies ist ein Test!";
              },
            ),
            field,
            OutlinedButton(
              onPressed: () {
                print("Parent: reload all");

                setState(() {});
              },
              child: Text("Reload all"),
            ),
          ],
        ),
      ),
    );
  }
}

This is my Child Class: It defines all the Fields inside the Grid. Inside of it I want to change some Propertys, in this case it is the Icon. But as well, this is only for testing so it could be anything that gets changed. The Trigger for the change should be as mentioned multiple times now in the parent class (first OutlinedButton in the Code above).

class Field extends StatefulWidget {
  final String text;
  final VoidCallback callback;

  final Function(int) func;
  final Function() returnValue;

  Function changeIcon;

  Field({this.text, this.callback, this.func, this.returnValue});

  _FieldState createState() => _FieldState();
}

class _FieldState extends State<Field> {
  IconData icon = Icons.add;

  @override
  void initState() {
    widget.changeIcon = (IconData icon) {
      setState(() {
        print("changeIcon");

        this.icon = icon;
      });
    };

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    print("Build Child");
    return IconButton(
      icon: Icon(icon),
      onPressed: () {
        print("Child: " + widget.text);

        if (widget.callback != null) widget.callback();

        String text = "";
        if (widget.func != null) text = widget.func(69);
        print("Child: " + text);

        String text2 = "";
        if (widget.returnValue != null) text2 = widget.returnValue();
        print("Child: " + text2);

        setState(() {
          icon = Icons.remove;
        });
      },
    );
  }
}

And if my current Way of trying to reach the Goal is completley off, I would love to change my Code accordingly. Again Thanks for helping.

P.S. I forgot to mention that the Game class is called from another class which is the starting point.

void main() {
  runApp(Website());
}

class Website extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Snake',
      home: Scaffold(
        body: Game(),
        backgroundColor: Color.fromRGBO(51, 107, 135, 1.0),
      ),
    );
  }
}

Now this is all I have in my Test Project.



Read more here: https://stackoverflow.com/questions/66266308/how-to-change-only-1-child-widget-from-a-parent-widget-in-flutter

Content Attribution

This content was originally published by Maxi at Recent Questions - Stack Overflow, and is syndicated here via their RSS feed. You can read the original post over there.

%d bloggers like this: