iosflutterdartsetstatepoint-of-sale

Flutter 'setState' of other Widget


i want to code a POS for german 'Fischbrötchen'. My problem is that the "View" of the Ordertabel dosn't update. I tried man things but nothing worked... can someone help me to point out my Problem ? So when i click a button a Order should add to the Orders List and then update the View to display the order.

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CupertinoApp(
      home: MyHomePage(),
      debugShowCheckedModeBanner: false,
      theme: CupertinoThemeData(
          brightness: Brightness.light, primaryColor: Colors.black54),
    );
  }
}

ValueNotifier<int> KundenId = ValueNotifier<int>(0);
List<Map<String, dynamic>> orders = [];

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

final List Getraenke = ["Fritz", "Wasser", "Bier"];

List<Map<String, dynamic>> items = [
  {'name': 'Möltenorter', 'price': '4 Euro'},
  {'name': 'Matjes', 'price': '4 Euro'},
  {'name': 'Bismarkt', 'price': '4 Euro'},
  {'name': 'Krabben', 'price': '5,50 Euro'},
  {'name': 'Lachs', 'price': '5.50 Euro'},
  {'name': 'Lachs Kalt', 'price': '5.50 Euro'},
];

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      child: RightSideContainer(),
    );
  }
}

class RightSideContainer extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => RightSideContainerState();
}

class RightSideContainerState extends State<RightSideContainer> {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        //left side, eingabe
        Column(
          children: [
            Text("Kasse"),
            Container(
                height: 600,
                width: MediaQuery.of(context).size.width / 2,
                child: Padding(
                    padding: EdgeInsets.all(5.0),
                    child: Container(
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(10),
                        color: Colors.black54,
                      ),
                      alignment: AlignmentDirectional.topStart,
                      child: OrderTable(),
                    ))),
          ],
        ),

        //right side, Ausgabe
        Container(
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(0),
              color: Colors.black.withOpacity(0.5),
            ),
            width: MediaQuery.of(context).size.width / 2,
            alignment: Alignment.centerRight,
            child: Column(
              children: [
                Container(
                  height: 500,
                  color: Colors.red,
                  child: GridView.builder(
                      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                          crossAxisCount: 4),
                      itemCount: items.length,
                      itemBuilder: (BuildContext context, int index) {
                        return ButtonPrefab(items_: items[index]);
                      }),
                ),
              ],
            ))
      ],
    );
  }
}

class ButtonPrefab extends StatelessWidget {
  final Map<String, dynamic> items_;

  const ButtonPrefab({required this.items_});

  void addOrder(name, price) {
    orders.add({
      'kundenId': 0,
      'bestellung': name,
      'price': price,
    });
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: CupertinoButton(
        child: Text(items_['name']),
        color: Colors.black54,
        padding: EdgeInsets.all(3),
        onPressed: () {
          print(orders);
          addOrder("name", 2.4);
          KundenId.value++;
          print(KundenId.value);
        },
      ),
    );
  }
}

class OrderTable extends StatefulWidget {
  @override
  State<OrderTable> createState() => _OrderTableState();
}

class _OrderTableState extends State<OrderTable> {
  @override
  void initState() {
    super.initState();
    setState(() {});
  }

  void update() {
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        children: [
          StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) {
            return DataTable(
              columnSpacing: 20,
              columns: [
                DataColumn(
                  label: Text(
                    'Kunden ID',
                    style: TextStyle(
                      fontWeight: FontWeight.bold,
                      fontSize: 16,
                    ),
                  ),
                ),
                DataColumn(
                  label: Text(
                    'Bestellung',
                    style: TextStyle(
                      fontWeight: FontWeight.bold,
                      fontSize: 16,
                    ),
                  ),
                ),
                DataColumn(
                  label: Text(
                    'Preis',
                    style: TextStyle(
                      fontWeight: FontWeight.bold,
                      fontSize: 16,
                    ),
                  ),
                ),
              ],
              rows: orders
                  .map(
                    (order) => DataRow(
                      cells: [
                        DataCell(
                          Text(
                            order['kundenId'].toString(),
                            style: TextStyle(fontSize: 16),
                          ),
                        ),
                        DataCell(
                          Text(
                            order['bestellung'],
                            style: TextStyle(fontSize: 16),
                          ),
                        ),
                        DataCell(
                          Text(
                            order['price'].toString(),
                            style: TextStyle(fontSize: 16),
                          ),
                        ),
                      ],
                    ),
                  )
                  .toList(),
            );
          })
        ],
      ),
    );
  }
}

I tried to use 'set State' in my Statefull Widget but is dosn't change anything..


Solution

  • Deleted my previous answer and tested your code... and got it working now.

    I see you have a Function named update() and you're even using it there, but should use it somewhere else as a callback Function. A callback Function helps you to edit values in your "previous" Widget that called this Widget. Read more here: How to pass callback in Flutter

    Also you have setState() in initState. Don't see the reason to have this there either. You should use setState in initState only for some kind of asyncronus reason, as explained here: Importance of Calling SetState inside initState

    Call setState in "previous" Widget on button press after adding your item by using a callback Function (for short keeping, here is only the modified code):

    class RightSideContainerState extends State<RightSideContainer> {
      void update() { //this is a new Function
        setState(() {});
      }
    
      @override
      Widget build(BuildContext context) {
        return Row(
          children: [
            //left side, eingabe
            Column(
              children: [
                Text("Kasse"),
                Container(
                    height: 600,
                    width: MediaQuery.of(context).size.width / 2,
                    child: Padding(
                        padding: EdgeInsets.all(5.0),
                        child: Container(
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(10),
                            color: Colors.black54,
                          ),
                          alignment: AlignmentDirectional.topStart,
                          child: OrderTable(),
                        ))),
              ],
            ),
    
            //right side, Ausgabe
            Container(
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(0),
                  color: Colors.black.withOpacity(0.5),
                ),
                width: MediaQuery.of(context).size.width / 2,
                alignment: Alignment.centerRight,
                child: Column(
                  children: [
                    Container(
                      height: 500,
                      color: Colors.red,
                      child: GridView.builder(
                          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                              crossAxisCount: 4),
                          itemCount: items.length,
                          itemBuilder: (BuildContext context, int index) {
                            return ButtonPrefab(items_: items[index], callbackFunction: update); //give the "update (setState)" Function to the "next" Widget for calling it later
                          }),
                    ),
                  ],
                ))
          ],
        );
      }
    }
    
    class ButtonPrefab extends StatelessWidget {
      final Map<String, dynamic> items_;
      final Function callbackFunction; //get the callback Function of the calling Widget
    
      const ButtonPrefab({required this.items_, required this.callbackFunction}); //get the callback Function of the calling Widget
    
      @override
      Widget build(BuildContext context) {
        return Padding(
          padding: const EdgeInsets.all(8.0),
          child: CupertinoButton(
            child: Text(items_['name']),
            color: Colors.black54,
            padding: EdgeInsets.all(3),
            onPressed: () {
              print(orders);
              // addOrder("name", 2.4); // you are always giving "name" and 2.4, but probably need to give the item that's being pushed
              addOrder(items_['name'], items_['price']); //like this
              KundenId.value++;
              print(KundenId.value);
              callbackFunction(); //this is the "update" Function I created in the calling Widget, but in this Widget it has a name "callbackFunction"
            },
          ),
        );
      }
    }
    
    class _OrderTableState extends State<OrderTable> {
      @override
      void initState() {
        super.initState();
        // setState(() {}); // not necessary
      }
    
      // void update() { // not necessary
      //   setState(() {});
      // }
    
    }