17
class ExtractArgumentsScreen extends StatelessWidget {
  static const routeName = '/extractArguments';

  double price = 0;

  _changeprice(num){
      setState(){
        price+ = num;
      }
    }

  @override
  Widget build(BuildContext context) {
    final MealArguments args = ModalRoute.of(context).settings.arguments;

    return Scaffold(
      appBar: AppBar(
        title: Text('MyApp'),
      ),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          SizedBox(height: 20,),

          ViewCard(args.combo,_changeprice()),
        ]));

This is the parent class. I passed the function _changePrice() to ViewCard so that I can change the value of the price later. This is giving me an

error "1 required argument(s) expected, but 0 found"

but I can't pass an argument to _changePrice as that defeats the whole purpose of using this callback. What I'm trying to implement is similar to what was suggested in Emit the data to parent Widget in Flutter.

The child class ViewCard passed this callback to another child called OneItem.

class OneItem extends StatefulWidget {
  OneItem(this.combo, this.index, this.changePrice);
  final Combo combo;
  final int index;
  final VoidCallback changePrice;

  @override
  State<StatefulWidget> createState() => OneItemState();
}

class OneItemState extends State<OneItem> {
  List<bool> Vals = new List();

  @override
  void initState() {
    super.initState();

    int count = widget.combo.items.length;

    Vals = List<bool>.generate(count, (_) => false);
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        Align(
          child: Text(widget.combo.items[widget.index].item),
          alignment: Alignment(-1, 0),
        ),
        Align(
            child: Text(widget.combo.items[widget.index].price),
            alignment: Alignment(0.1, 0)),
        Align(
            child: Checkbox(
              value: Vals[widget.index],
              onChanged: (bool value) {
                setState(() {
                  Vals[widget.index] = value;
                  if(value == true){double childPrice = double.parse(widget.combo.items[widget.index].price); }
                  else{double val = double.parse(widget.combo.items[widget.index].price); 
                        double childPrice = -1*val;}
                  widget.changePrice(childPrice);                        
                  //widget.changePrice();
                });
              },
            ),
            alignment: Alignment(0.6, 0)),
      ],
    );
  }
}
Yashwardhan Pauranik
  • 5,370
  • 5
  • 42
  • 65
Hemabh
  • 423
  • 2
  • 5
  • 18

2 Answers2

20

You could declare a Function callback, like this:

final void Function(double price) changePrice;

Here another example to understand it better:

final bool Function(String id, double price) updateItem;

bool isPriceUpdated = widget.updateItem("item1", 7.5);
Pablo Barrera
  • 10,387
  • 3
  • 28
  • 49
12

You call widget.changePrice(childPrice); from OneItemState, so changePrice can't be VoidCallback

typedef IntCallback = Function(int num);

/* ... */

class OneItem extends StatefulWidget {
  OneItem(this.combo, this.index, this.changePrice);
  final Combo combo;
  final int index;
  final IntCallback changePrice;

  @override
  State<StatefulWidget> createState() => OneItemState();
}

/* ... */

ViewCard(args.combo, _changeprice) // function name without braces

I would do it like this

Andrii Turkovskyi
  • 27,554
  • 16
  • 95
  • 105