Anan Saadi
Anan Saadi

Reputation: 338

Adding a new element to another screen's list in flutter

I have a list in Page_2.dart:

final List<Trans> transactions = [
    Trans(false, 20),
  ];

that takes a custom class widget, Trans that takes a Boolean and a double and displays them in a Row, and I have button to add a new element to transactions,

RaisedButton(
 onPressed: () {
  setState(
          () {
       transactions.add(
       Trans(true, -50));
       },
     );
   },
  child: const Text("Add Transaction"),
),

and I want to have a button inside page_3.dart that does the same thing which is adding a new adding a new Trans to transactions

Upvotes: 1

Views: 1900

Answers (2)

BambinoUA
BambinoUA

Reputation: 7100

Usually there are two methods of widget interaction: callbacks (when one widget provides a callback and other one call it back) or streams (when one widget provides a stream controller and other one uses those controller to send events to stream). Callbacks and events are processed by widget-initiator.

  1. Create a ValueSetter parameter in Page3 widget and create it like:
// in Page2
final page3 = Page3(callback: (trans) {
  transactions.add(trans);
}

// in Page3
onPressed: () {
  widget.callback(Trans(...)); // if Page3 us stateful
}
  1. Create a StreamController<Trans> state member in Page2and pass it as parameter toPage3`.
// in Page2
@override
void initState() {
  super.initState();
  controller.stream.listen((trans) {
    transactions.add(trans);
  });
}
// in Page3
onPressed: () {
  widget.controller.add(Trans(...));
}

Upvotes: 0

bluenile
bluenile

Reputation: 6029

All you need to do is pass the function 'add transaction' from 'Page 2' to 'Page 3'. You have to make sure that the function 'add transaction' accepts 'Trans' as a parameter and it also calls setState for Page 2. In Page 3 you have to pass your 'Trans(true, -50)' as the parameter to the 'add transaction' function that is received from 'Page 2'. The 'add transaction' function may be run in the onPressed method of RaisedButton on 'Page 3'. Please see the code below :

import 'package:flutter/material.dart';
import 'dart:math' as math;

final Color darkBlue = const Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

extension Ex on double {
  double toPrecision(int n) => double.parse(toStringAsFixed(n));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(
          title: const Text("Flutter Demo App"),
        ),
        body: Center(
          child: MyWidget(),
        ),
      ),
    );
  }
}

class MyWidget extends StatefulWidget {
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  void _addTransaction(Trans transaction) {
    setState(() {
      transactions.add(transaction);
    });
  }

  final List<Trans> transactions = [
    const Trans(myBool: false, myDouble: 20),
    const Trans(myBool: true, myDouble: -50),
    const Trans(myBool: false, myDouble: 110),
    const Trans(myBool: false, myDouble: 35.5),
  ];

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Container(
          height: MediaQuery.of(context).size.height * .7,
          child: Scrollbar(
            showTrackOnHover: true,
            child: ListView.builder(
              itemCount: transactions.length,
              itemBuilder: (context, index) {
                return ListTile(
                  title: transactions[index],
                );
              },
            ),
          ),
        ),
        RaisedButton(
          onPressed: () {
            final rnd = math.Random();
            _addTransaction(
              Trans(
                myBool: rnd.nextBool(),
                myDouble: rnd.nextDouble().toPrecision(2) + rnd.nextInt(100),
              ),
            );
          },
          child: const Text("Add Transaction"),
        ),
        RaisedButton(
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => Page3(addTran: _addTransaction),
              ),
            );
          },
          child: const Text("Page 3"),
        ),
      ],
    );
  }
}

class Trans extends StatelessWidget {
  final myBool;
  final myDouble;

  const Trans({Key key, this.myBool, this.myDouble}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Text("Transaction: ${myBool.toString()}  ${myDouble.toString()}")
      ],
    );
  }
}

class Page3 extends StatefulWidget {
  final Function addTran;
  const Page3({Key key, this.addTran}) : super(key: key);
  @override
  _Page3State createState() => _Page3State();
}

class _Page3State extends State<Page3> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Page 3"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () => widget.addTran(
            const Trans(myBool: true, myDouble: 50),
          ),
          child: const Text("Add Transaction"),
        ),
      ),
    );
  }
}

Note : even though in my example code above the widget 'Page 3' is in the same file. You may make a separate library for 'Page 3' as usual by importing material.dart.

Upvotes: 2

Related Questions