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
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?
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:
flutter pub add provider
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:
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.