skip to Main Content

Is it possible to update a variable outside a widget while calling it ?
Here’s an example :

class Widget1 extends StatefulWidget {

  @override
  State<Widget1> createState() => _Widget1State();
}

class _Widget1State extends State<Widget1> {
  String example = 'A';

  @override
  Widget build(BuildContext context) {
    return Column(children: [
      Text(example),
      Widget2(example: example)
    ],);
  }
}
class Widget2 extends StatefulWidget {
  final String example;

  Widget2({required this.example});

  @override
  State<Widget2> createState() => _Widget2State();
}

class _Widget2State extends State<Widget2> {

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () => setState(() {
        widget.example = 'B'
      }),
      child: Text('update !'),
    );
  }
}

The idea here is that I want to update example using a button outside the widget.

This code is not working : example = 'A' no matter if I click the button or not, but I don’t understand why since I’m calling the same variable.

Is there a simple solution to achieve this ? (by simple, I mean without the need of Provider or else.)

3

Answers


  1. You can use callback method. Parent widget needed to updated, so setState is needed to be trigger on Widget1.

    class Widget1 extends StatefulWidget {
      @override
      State<Widget1> createState() => _Widget1State();
    }
    
    class _Widget1State extends State<Widget1> {
      String example = 'A';
    
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [
            Text(example),
            Widget2(
              example: example,
              callback: (p0) {
                setState(() {
                  example = p0;
                });
              },
            ),
          ],
        );
      }
    }
    
    class Widget2 extends StatefulWidget {
      final String example;
      final Function(String) callback;
      Widget2({
        required this.example,
        required this.callback,
      });
    
      @override
      State<Widget2> createState() => _Widget2State();
    }
    
    class _Widget2State extends State<Widget2> {
      @override
      Widget build(BuildContext context) {
        return ElevatedButton(
          onPressed: () {
            widget.callback("new data");
          },
          child: Text('update !'),
        );
      }
    }
    
    Login or Signup to reply.
  2. You can use Notifiers, here is an example:

    import 'package:flutter/material.dart';
    
    class ExampleNotifier with ChangeNotifier {
      String example = 'A';
    
      ExampleNotifier();    
    
      setText(string x) {
        example = x;
        notifyListeners();
    
      }    
    }
    

    and then use it like:

    class Widget1 extends StatefulWidget {
      @override
      State<Widget1> createState() => _Widget1State();
    }
    
    class _Widget1State extends State<Widget1> {
    
      @override
      Widget build(BuildContext context) {
    
    var exampleNotifier = Provider.of<ExampleNotifier>(context);
        return Column(
          children: [
            Text(exampleNotifier.example),
            Widget2(),
          ],
        );
      }
    }
    
    class Widget2 extends StatefulWidget {
    
      @override
      State<Widget2> createState() => _Widget2State();
    }
    
    class _Widget2State extends State<Widget2> {
      @override
      Widget build(BuildContext context) {
    
        var exampleNotifier = Provider.of<ExampleNotifier>(context, listen: false);
    
        return ElevatedButton(
          onPressed: () {
            exampleNotifier.setText('B');
          },
          child: Text('update !'),
        );
      }
    }
    
    Login or Signup to reply.
  3. If you want to use setState, you can use this

    class Widget1 extends StatefulWidget {
      @override
      State<Widget1> createState() => _Widget1State();
    }
    
    class _Widget1State extends State<Widget1> {
      String example = 'A';
    
      void changeExample() {
        setState(() => example = "B");
      }
    
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [Text(example), Widget2(changeExample: changeExample)],
        );
      }
    }
    
    class Widget2 extends StatelessWidget {
      final void Function() changeExample;
    
      Widget2({required this.changeExample});
    
      @override
      Widget build(BuildContext context) {
        return ElevatedButton(
          onPressed: changeExample,
          child: Text('update !'),
        );
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search