how to setup a function in my code as it's own stateful widget and then pass variables to it

I have written the below code and it is working as intended. when a button is pressed, a string variable (displayText) is updated with the text from the button. then, the function UpdateWidget reads the displayText string and use a switch/case to determine what further buttons to display, then when those new buttons are pressed, it saves the selection as the switchtext String.

class TestPage extends StatefulWidget {
  const TestPage({Key? key}) : super(key: key);

  @override
  State<TestPage> createState() => _TestPageState();
}

class _TestPageState extends State<TestPage> {
  String displayText = '';
  String switchText = '';
  var displayWidget = Container();

  void updateWidget(String displayText) {
    switch (displayText) {
      case 'Option A':
        displayWidget = Container(
          child: Column(
            children: [
              Button(
                  color: Colors.red,
                  onTap: (val) {
                    setState(() {
                      switchText = val;
                      print(switchText);
                    });
                  },
                  text: 'Option 1'),
              SizedBox(
                height: 10,
              ),
              Button(
                  color: Colors.blue,
                  onTap: (val) {
                    setState(() {
                      switchText = val;
                      print(switchText);
                    });
                  },
                  text: 'Option 2'),
            ],
          ),
        );
        break;
      case 'Option B':
        displayWidget = Container(
          child: Column(
            children: [
              Button(
                  color: Colors.green,
                  onTap: (val) {
                    setState(() {
                      switchText = val;
                      print(switchText);
                    });
                  },
                  text: 'Option 3'),
              SizedBox(
                height: 10,
              ),
              Button(
                  color: Colors.yellow,
                  onTap: (val) {
                    setState(() {
                      switchText = val;
                      print(switchText);
                    });
                  },
                  text: 'Option 4'),
            ],
          ),
        );
        break;

      default:
        displayWidget = Container();
        break;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          SizedBox(
            height: 100,
          ),
          Row(
            children: [
              Button(
                  color: Colors.yellow,
                  onTap: (val) {
                    setState(() {
                      displayText = val;
                      updateWidget(val!);
                      print(displayText);
                    });
                  },
                  text: 'Option A'),
              SizedBox(
                width: 5,
              ),
              Button(
                  color: Colors.yellow,
                  onTap: (val) {
                    setState(() {
                      displayText = val;
                      updateWidget(val!);
                      print(displayText);
                    });
                  },
                  text: 'Option B')
            ],
          ),
          SizedBox(
            height: 30,
          ),
          displayWidget,
        ],
      ),
    );
  }
}

class Button extends StatelessWidget {
  Button({required this.color, required this.onTap, required this.text});

  final Color color;
  final String text;
  final ValueChanged? onTap;
  @override
  Widget build(BuildContext context) {
    return InkWell(
        onTap: () {
          if (onTap != null) {
            onTap!(text);
          }
        },
        child: Container(
          height: 50,
          width: 100,
          color: color,
          child: Center(
            child: Text(
              text,
              style: TextStyle(color: Colors.black),
            ),
          ),
        ));
  }
}

What I would like to do and I was hoping someone would be able to show me please, is how do I turn the
UpdateWidget function into it’s own stateful class and then pass the string displayText to it so it knows what further buttons to display? when it is called upon. I would then need those further buttons to update the switchText string when they are pressed please.

thank you so much and any help would be greatly appreciated.

cheers

>Solution :

You need to pass displayText and onTap function, you can create this class:

class DisplayWidget extends StatelessWidget {
  final Function(String)? onTap;
  final String displayText;
  const DisplayWidget({Key? key, required this.displayText, this.onTap}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    switch (displayText) {
      case 'Option A':
        return Container(
          child: Column(
            children: [
              Button(
                  color: Colors.red,
                  onTap: onTap,
                  text: 'Option 1'),
              SizedBox(
                height: 10,
              ),
              Button(
                  color: Colors.blue,
                  onTap: onTap,
                  text: 'Option 2'),
            ],
          ),
        );
      case 'Option B':
        return Container(
          child: Column(
            children: [
              Button(
                  color: Colors.green,
                  onTap: (val) {
                    setState(() {
                      switchText = val;
                      print(switchText);
                    });
                  },
                  text: 'Option 3'),
              SizedBox(
                height: 10,
              ),
              Button(
                  color: Colors.yellow,
                  onTap: (val) {
                    setState(() {
                      switchText = val;
                      print(switchText);
                    });
                  },
                  text: 'Option 4'),
            ],
          ),
        );

      default:
        return Container();
    }
  }
}

and use it like this:

return Scaffold(
  body: Column(
    children: [
      SizedBox(
        height: 100,
      ),
      Row(
        children: [
          Button(
              color: Colors.yellow,
              onTap: (val) {
                setState(() {
                  displayText = val;
                  print(displayText);
                });
              },
              text: 'Option A'),
          SizedBox(
            width: 5,
          ),
          Button(
              color: Colors.yellow,
              onTap: (val) {
                setState(() {
                  displayText = val;
                  print(displayText);
                });
              },
              text: 'Option B')
        ],
      ),
      SizedBox(
        height: 30,
      ),
      DisplayWidget(displayText: displayText,
             onTap:(val){
                 setState(() {
                  switchText = val;
                  print(switchText);
                 });
             }),
    ],
  ),
);

and also change your Button class to this:

class Button extends StatelessWidget {
  Button({required this.color, required this.onTap, required this.text});

  final Color color;
  final String text;
  final Function(String)? onTap; // <-- change this
  
  @override
  Widget build(BuildContext context) {
    return InkWell(
        onTap: () {
          if (onTap != null) {
            onTap!(text);
          }
        },
        child: Container(
          height: 50,
          width: 100,
          color: color,
          child: Center(
            child: Text(
              text,
              style: TextStyle(color: Colors.black),
            ),
          ),
        ));
  }
}

Leave a Reply