-1

I want to change the value of the text field in MyButton, such that, each time the button is clicked, the value is changed. I have set the value as a attribute in MyButton and passed a function from MyButtonRow to MyButton that will be executed everytime it is clicked. In that function, I want to change the attribute "myString" of MyButton, so it will automatically update the text field.

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>[MyButton(onTap: (){
          print("Notify me");
          //I want to change the myText attribute of MyButton here
        }, myText: "Hello",)],));
  }
}

class MyButton extends StatefulWidget {
  final Function onTap;
  final String myText;
  const MyButton({Key? key, required this.onTap, required this.myText}) : super(key: key);

  @override
  _MyButtonState createState() => _MyButtonState();
}

class _MyButtonState extends State<MyButton> {
  var onTap;
  var myString;
  @override
  void initState() {
    onTap = widget.onTap;
    myString = widget.myText;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return TextButton(onPressed:onTap,
        child: Text(myString));
  }
}

**EDIT**

Both the answers, by @Yeasin Sheikh and @Jav T were correct. But this brought me to another question, "Is there a way i can access that attribute of MyButton in MyButtonRow"

Joel
  • 239
  • 3
  • 21
  • I guess you want sth like this? https://stackoverflow.com/questions/48481590/how-to-set-update-state-of-statefulwidget-from-other-statefulwidget-in-flutter – Xoltawn Nov 20 '21 at 15:41

2 Answers2

1

You can create a method or assign method like inside _MyButtonState's build

 onPressed: () {
        onTap();
        setState(() {
          myString = "newValue";
        });
      },

To use MyButton's myText that is coming though constructor, use widget.myText as @Jav T descried.

It is not necessary to make this StatefulWidget in this case, you can simply use StatelessWidget for MyButton.

class MyButton extends StatelessWidget {
  final Function onTap;
  final String myText;

  const MyButton({
    Key? key,
    required this.onTap,
    required this.myText,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return TextButton(
      onPressed: () => onTap(),
      child: Text(myText),
    );
  }
}
Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56
1

Issue is that you are passing the newValue as a constructor parameter and assigning it to a local variable which is retained in state. Whenever a rebuild is called, the initState function is never called again, just the first time, I would recommend that instead of using:

@override
  Widget build(BuildContext context) {
    return TextButton(onPressed:onTap,
        child: Text(myString));
  }

You go ahead and use:

@override
      Widget build(BuildContext context) {
        return TextButton(onPressed:onTap,
            child: Text(widget.myText));
      }

In this case, the value will be updated whenever the parent rebuilds your widget. Make sense?

However, you cannot change the attributes of a widget after it is built - How to access/change an attribute of a Widget in Flutter

Joel
  • 239
  • 3
  • 21
Jav T
  • 478
  • 3
  • 12