Introduction
This post is part of my 100DaysOfCode series. In this series, I write about what I am learning on this challenge. For this challenge, I will be learning flutter and firebase by building an Agriculture Management Information System.
Recap
On Day 16 we discussed how to reuse a screen widget to personalize our app for the currently signed-in user.
Overview
In this post, we'll discuss how to use our farmer form screen to add and update cloud firestore documents. We have already implemented the Add functionality so we will focus on the update functionality.
Location Filter Enum
The first step is to create a Farm Type enum. enum FarmType { add, update }
. This enum value will be passed to the FarmerFormScreen()
widget to modify the screen into an add farmer form and an update farmer form.
class FarmerFormScreen extends StatefulWidget {
static String routeName = 'AddFarmerScreen';
final FarmerServiceModel? farmerModel;
final FormType formType;
FarmerFormScreen({
this.farmerModel,
required this.formType,
Key? key,
}) : super(key: key);
@override
_FarmerFormScreenController createState() => _FarmerFormScreenController();
}
This widget accepts an optional final FarmerServiceModel? farmerModel;
that will be used to update the farmer document.
Text Form Field widget with Controller
class _FarmerFormScreenController extends State<FarmerFormScreen> {
@override
Widget build(BuildContext context) => _FarmerFormScreenView(this);
late TextEditingController dateOfBirthController;
@override
void initState() {
super.initState();
dateOfBirthController = TextEditingController();
if (widget.formType == FormType.update) {
dateOfBirthController = TextEditingController(
text: DateFormat.yMMMd().format(widget.farmerModel!.dateOfBirth!));
} else {
dateOfBirthController = TextEditingController();
}
}
The date of birth text form field initial value will be null when adding a farmer and the farmer date of birth when updating a farmer document.
Text Form Field widget without controller
class LastNameTextFormField extends StatelessWidget {
const LastNameTextFormField({
Key? key,
required this.state,
}) : super(key: key);
final _FarmerFormScreenController state;
@override
Widget build(BuildContext context) {
return TextFormField(
decoration: FormStyles.textFieldDecoration(labelText: 'Last Name'),
focusNode: state.lastNameFocusNode,
textInputAction: TextInputAction.next,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: state.farmer.validateRequiredField,
onSaved: state.farmer.saveLastName,
initialValue: state.widget.formType == FormType.update
? state.widget.farmerModel!.lastName
: null,
);
}
}
The initialValue is assigned the farmer document lastname value if state.widget.formType == FormType.update
and null otherwise. This same methodology was repeated for all other form field widgets.
Wrap Up
In this post, we discussed how to reuse our farmer form screen widget to add and update a farmer document.
Connect with me
Thank you for reading my post. Feel free to subscribe below to join me on the #100DaysOfCodeChallenge or connect with me on LinkedIn and Twitter. You can also buy me a book to show your support.
Top comments (2)
Can you elaborate on
_FarmerFormScreenView
? Not sure what to add in my case.Sure, Instead of returning a scaffold and the other widget that will make up the
FarmFormScreen
I returned a_FarmerFormScreenView
. This class is passed the entire State object. This is done to create an extra layer of separation between my code logic and my UI. I am now free to swap out the_FarmerFormScreenView
for a_FarmerFormScreenMobileView
etc and all my different views (UI) will have access to my code logic.