I am trying to clean up my code a lot. I have a form that I realise I use multiple times in my app. So I wanted to turn the form into its own stateful widget so I could easily re-use it. Unfortunately this is proving more difficult than I thought.
The form is first used in the app to add items. I then want to re-use that same form to edit items and change values in those text fields.
I call the new widget that I created:
body: const GearForm(
onSaveFunctionType: 'add',
itemID: 'none',
itemManufacturer: 'hi',
itemName: '',
itemType: 'test',
itemVolume: '',
itemWeight: '',
packCategory: '',
tempRating: '',
),
If I am passing arguments into the widget though they do not show up in the form when I am testing:
class GearForm extends StatefulWidget {
const GearForm(
{Key? key,
required this.onSaveFunctionType,
required this.itemID,
required this.itemName,
required this.itemManufacturer,
required this.itemType,
required this.packCategory,
required this.itemWeight,
required this.tempRating,
required this.itemVolume})
: super(key: key);
final String onSaveFunctionType;
final String itemID;
final String itemName;
final String itemManufacturer;
final String itemType;
final String packCategory;
final String itemWeight;
final String tempRating;
final String itemVolume;
@override
State<GearForm> createState() => _GearFormState();
}
//define category stream stream
Stream<DocumentSnapshot<Map<String, dynamic>>> streamUserCategories() {
FirebaseFirestore db = FirebaseFirestore.instance;
String userID = FirebaseAuth.instance.currentUser!.uid;
return db.collection('UserPackCategoryList').doc(userID).snapshots();
}
class _GearFormState extends State<GearForm> {
FirebaseAnalytics analytics = FirebaseAnalytics.instance;
FirebaseFirestore db = FirebaseFirestore.instance;
String userID = FirebaseAuth.instance.currentUser!.uid;
//text editing controllers
TextEditingController itemNameController = TextEditingController();
TextEditingController manufacturerController = TextEditingController();
TextEditingController itemTypeController = TextEditingController();
TextEditingController packCategoryController = TextEditingController();
TextEditingController itemWeightController = TextEditingController();
TextEditingController temperatureRatingController = TextEditingController();
TextEditingController volumeController = TextEditingController();
@override
Widget build(BuildContext context) {
//get entitlements from revenue cat
final Entitlement entitlement =
Provider.of<RevenueCatProvider>(context).entitlement;
print(widget.itemManufacturer);
//set initial controller values
itemNameController.text = widget.itemName;
manufacturerController.text = widget.itemManufacturer;
itemTypeController.text = widget.itemType;
packCategoryController.text = widget.packCategory;
itemWeightController.text = widget.itemWeight;
temperatureRatingController.text = widget.tempRating;
volumeController.text = widget.itemVolume;
The odd part is if I did a cmd+s in visual studio code then all the value would magically appear. Since the Cmd+s worked I thought it was showing the values on rebuild so I tried wrappign everythign in setState:
@override
Widget build(BuildContext context) {
//get entitlements from revenue cat
final Entitlement entitlement =
Provider.of<RevenueCatProvider>(context).entitlement;
print(widget.itemManufacturer);
setState(() {
//set initial controller values
itemNameController.text = widget.itemName;
manufacturerController.text = widget.itemManufacturer;
itemTypeController.text = widget.itemType;
packCategoryController.text = widget.packCategory;
itemWeightController.text = widget.itemWeight;
temperatureRatingController.text = widget.tempRating;
volumeController.text = widget.itemVolume;
});
but that didnt fix the issue either…
Update:
I did soem further troubleshooting and tried initState:
@override
void initState() {
super.initState();
print(widget.itemManufacturer);
itemNameController.text = widget.itemName;
manufacturerController.text = widget.itemManufacturer;
itemTypeController.text = widget.itemType;
packCategoryController.text = widget.packCategory;
itemWeightController.text = widget.itemWeight;
temperatureRatingController.text = widget.tempRating;
volumeController.text = widget.itemVolume;
//set initial controller values
}
What is super odd here is that my print(widget.itemManufacturer);
works fine and I see the correct value. But it is not being assigned to the manufacturerController.text = widget.itemManufacturer;
a few lines down.
2
Answers
The reason why the value were not showing in my form fields was because I am using autocomplete. Autocomplete upon further research has an initial Value field:
Once I used that initalValue field all updated accordingly.
Use
initState
or you can uselate