skip to Main Content

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


  1. Chosen as BEST ANSWER

    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.


  2. Use initState or you can use late

      late TextEditingController itemNameController =
          TextEditingController.fromValue(TextEditingValue(text: widget.itemName));
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search