0

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.

Ten Digit Grid
  • 1,315
  • 4
  • 22
  • 43
  • 1
    If you want to set initial values, you do in the onInit() method and not in the build() method. Also, you don't need to set controller values within set state, you can directly set values. – OMi Shah Nov 03 '22 at 19:14
  • @OMiShah I tried this but it didnt work: override // ignore: must_call_super initState() { //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; // ignore: avoid_print print("initState Called"); } – Ten Digit Grid Nov 03 '22 at 19:20

2 Answers2

0

Use initState or you can use late

  late TextEditingController itemNameController =
      TextEditingController.fromValue(TextEditingValue(text: widget.itemName));
Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56
0

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:

initialValue: TextEditingValue(text: manufacturerController.text),

Once I used that initalValue field all updated accordingly.

Ten Digit Grid
  • 1,315
  • 4
  • 22
  • 43