skip to Main Content

I have my first screen that has some form fields. when clicking the button its creating an object
from the form fields and adding it to a List. after adding couple of objects you can move to a review screen, in which we can see the list we just created in a listview. And when you want to edit an object I have a button on each listview card for editing. I want that when an object is clicked I will reuse the first screen with the form fields to edit this object, essentially it will pass back the List with all the objects and the object id like to edit. the object will fill the form fields and than will be edited by the user and replace tha current object that we wish to edit. after editing id like to get back to the second screen with the updated list to show in the listview.
this is the form field screen:

// ignore_for_file: prefer_const_constructors, use_build_context_synchronously, non_constant_identifier_names, avoid_print, curly_braces_in_flow_control_structures

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:titan_coach_app/Exercise.dart';
import 'package:titan_coach_app/WorkoutReviewScreen.dart';
import 'main.dart';

final training_list = <Exercise>[];

class TrainingCreateScreen extends StatefulWidget {
  _TrainingCreateScreenState createState() => _TrainingCreateScreenState();
}
final _exerciseNotes = TextEditingController();

class _TrainingCreateScreenState extends State<TrainingCreateScreen> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(user?.email ?? 'No email connected'),
        backgroundColor: Colors.amber,
        actions: [
          buildSeeingAllTheExercises()
        ],
      ),
      body: AnnotatedRegion<SystemUiOverlayStyle>(
        value: SystemUiOverlayStyle.dark,
        child: Stack(
          children: [
            Container(
              height: double.infinity,
              width: double.infinity,
              decoration: BoxDecoration(
                color: Color(0xff333333),
              ),
              child: SingleChildScrollView(
                padding: EdgeInsets.symmetric(vertical: 50),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    buildExercise(),
                    SizedBox(height: 10),
                    buildExerciseBt(),
                    SizedBox(height: 10),
                    buildUploadTrainingBt(),
                    FloatingActionButton(
                      onPressed: () async {
                        try {
                          await FirebaseAuth.instance.signOut();
                          // After signing out, navigate back to the login screen
                          Navigator.pushReplacement(
                            context,
                            MaterialPageRoute(builder: (context) => LoginScreen()),
                          );
                        } catch (e) {
                          print('Sign out error: $e');
                        }
                      },
                      child: Text("Sign Out"),
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }


// just the forms nothing intresting
  Widget buildExercise() {
    return Form(

              ),
            ),
          ],
        ),
      ),
    );
  }


  //button for adding an exercise to the list
  Widget buildExerciseBt() {
    return FloatingActionButton(
      onPressed: () {
        if(_formKey.currentState!.validate()){
          training_list.add(Exercise(
              _exerciseName.text,
              int.tryParse(_numberOfSets.text) ?? 0,
              int.tryParse(_numberOfReps.text) ?? 0,
              int.tryParse(_exerciseRPE.text) ?? 0,
              _exerciseNotes.text.isEmpty? '' : _exerciseNotes.text)
          );
          final snAdeded = SnackBar(
            content: Text("Added to the workout"),
            action: SnackBarAction(label: "undo",onPressed: (){training_list.removeLast();}),);
          ScaffoldMessenger.of(context).showSnackBar(snAdeded);
        }
        print(training_list);
      },
      backgroundColor: Colors.amber,
      child: Icon(Icons.add),
    );
  }



  //Button for going to the screen in which you can see all the exercises
  Widget buildSeeingAllTheExercises()
  {
    return ElevatedButton(
        onPressed: (){
          Navigator.push(context, MaterialPageRoute(builder:
              (context) => WorkoutReviewScreen(training_list: training_list)));
        },
        style: ButtonStyle(
          elevation: MaterialStateProperty.all(0),
          backgroundColor: MaterialStateProperty.all<Color>(Colors.transparent),
        ),
        child: Icon(Icons.check));
  }

  // For the number forms to check if they are numbers
  numberValidator(String value) {
  }
}

this is the second screen with the listview:

// ignore_for_file: prefer_const_constructors

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

import 'Exercise.dart';

class WorkoutReviewScreen extends StatefulWidget {
  final List<Exercise> training_list;

  WorkoutReviewScreen({required this.training_list});

  @override
  State<WorkoutReviewScreen> createState() => _WorkoutReviewScreenState();
}

class _WorkoutReviewScreenState extends State<WorkoutReviewScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(user?.email ?? 'No email connected'),
        backgroundColor: Colors.amber,
      ),
      body: ListView.builder(
        padding: EdgeInsets.symmetric(horizontal: 30,vertical: 10),
        itemCount: training_list.length,
        itemBuilder: (context, index) =>
            Container(
                margin: EdgeInsets.symmetric(vertical: 3),
                child: exersiceCard(training_list[index])),
      ),
      backgroundColor: Color(0xff333333),
    );
  }


  //this is the block in which each exersice locates in the list view
  Widget exersiceCard(Exercise exercise)
  {
    return Card(
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 7,vertical: 12),
        child: Column(
            Row(
              mainAxisAlignment: MainAxisAlignment.end,
              children: <Widget>[
                buildEditExerciseBt(exercise),
                buildDeleteExerciseBt(exercise),
              ],
            ),
          ],
        ),
      ),
    );
  }


  /// used to delete the exercise from the list of exercises
  Widget buildDeleteExerciseBt(Exercise delExercise)
  {
    return IconButton(
  }
  /// used to edit the exercise from the list of exercises
  Widget buildEditExerciseBt(Exercise editExercise)
  {
    return IconButton(
        onPressed: (){
          Navigator.
          push(context,
              MaterialPageRoute(builder: (context) => TrainingCreateScreen(editExercise)));
        },
        icon: Icon(
          Icons.edit,
        ));
  }
}

I tried to call the form field screen when editing but it asked to create a constructor. I don’t want to create a constructor because I have another screen that calls the form field screen in which doesn’t have any object/list to provide.

2

Answers


  1. You could try to use package go_router to easily pass arguments between views.

    Check this thread it may help you decide and check how to pass arguments between views : Flutter: go_router how to pass multiple parameters to other screen?

    Login or Signup to reply.
  2. With too much respect to my friends answers, navigating with arguments is not a good approach when you need consistent access to data.
    The best and most professional way to do this is using the Flutter Provider package.
    Here is a brief explanation:

    1. Install Provider using flutter pub add provider
    2. Create a Model Class: Typically, you create a model class that holds the data you want to share across your widgets. This class should extend ChangeNotifier from the Provider package. Here’s an example of a simple counter model:
    class CounterModel extends ChangeNotifier {
      int _count = 0;
    
      int get count => _count;
    
      void increment() {
        _count++;
        notifyListeners(); // Notify listeners when the data changes
      }
    }
    
    1. Wrap the App with Provider: In your main.dart (or wherever you define your app’s entry point), wrap your MaterialApp or the root widget of your app with a ChangeNotifierProvider. This provider will expose your model to the widget tree.
    void main() {
      runApp(
        ChangeNotifierProvider(
          create: (context) => CounterModel(),
          child: MyApp(),
        ),
      );
    }
    
    1. Access the Model in Widgets:

    You can access your model anywhere in the widget tree below the ChangeNotifierProvider using the Provider.of method. Here’s how you can access and use the counter value:

    class MyHomePage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        final counterModel = Provider.of<CounterModel>(context);
    
        return Scaffold(
          appBar: AppBar(
            title: Text('Flutter Provider Example'),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  'Counter Value:',
                ),
                Text(
                  '${counterModel.count}',
                  style: TextStyle(fontSize: 24),
                ),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () {
              counterModel.increment();
            },
            child: Icon(Icons.add),
          ),
        );
      }
    }
    
    1. Listening to Changes:

    Widgets that use the Provider.of method will automatically rebuild when notifyListeners() is called in the model. This allows you to keep your UI in sync with your data.

    IMPORTANT NOTE
    This was just a sample for a counter app… Build a model for your workouts or exercises or whatever you want based on the provided sample.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search