Home > Software engineering >  type 'int' is not a subtype of type 'String?' in TextFormField
type 'int' is not a subtype of type 'String?' in TextFormField

Time:03-06

I have a problem with TextFormField initial values. It all works well until I activate (start typing) the TextFormField, then I get the error (type 'int' is not a subtype of type 'String?') and my Recipe id is reset to null. Disclaimer: All data map variables are of type String or List. Thanks in advance!

class NutritionScreen extends StatefulWidget {
  static const routeName = '/route-name';
  @override
  _NutritionScreenState createState() => _NutritionScreenState();
}

class _NutritionScreenState extends State<NutritionScreen> {
  final _formKey = GlobalKey<FormState>();
  bool isLoading = false;
  late RecipeProvider functions;
  Map<String, dynamic> data = {};
  Recipe newRecipe = Recipe(
    title: '',
    description: '',
    id: '',
    ingredients: [''],
    steps: [''],
    creatorId: '',
    kcal: 0,
    p: 0,
    c: 0,
    f: 0,
    servings: 0,
  );
  @override
  initState() {
    super.initState();
    Future.delayed(Duration.zero, () {
      Map<String, dynamic> otherData =
          ModalRoute.of(context)!.settings.arguments as Map<String, dynamic>;
      data = otherData;
      functions = Provider.of<RecipeProvider>(context, listen: false);
    });
  }

  Future<void> saveForm() async {
    String userId = FirebaseAuth.instance.currentUser!.uid;
    bool isValid = _formKey.currentState!.validate();
    setState(() {
      isLoading = true;
    });
    if (isValid == true) {
      try {
        final storagePath = FirebaseStorage.instance
          .ref()
          .child('recipe_image')
          .child(userId   '.jpg');

      await storagePath.putFile(data['image']);
      final imageUrl = await storagePath.getDownloadURL();
      newRecipe.imageUrl = imageUrl;
        _formKey.currentState!.save();
        if (data['id'] == '') {
          await functions.addRecipe(newRecipe);
        } else {
          await functions.editRecipe(newRecipe);
        }
        Navigator.of(context).pushReplacementNamed(MainScreen.routeName);
      } catch (error) {
        rethrow;
      }
    }
    setState(() {
      isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    print(data['id']);
    Size deviceSize = MediaQuery.of(context).size;
    return Scaffold(
      resizeToAvoidBottomInset: true,
      appBar: AppBar(
        title: Text(
          'Add Nutrition Data',
          style: Theme.of(context).textTheme.headline1,
        ),
      ),
      body: isLoading == true
          ? const Center(
              child: CircularProgressIndicator(
                semanticsLabel: 'Loading',
              ),
            )
          : Form(
              key: _formKey,
              child: ListView(
                children: [
                  const SizedBox(
                    height: 20,
                  ),
                  NutritionRow(
                    'Calories',
                    TextFormField(
                      initialValue: data['id'] == ''
                          ? '0'
                          : data['kcal'],
                      validator: (value) {
                        if (int.parse(value!) <= 0) {
                          return 'Please enter a valid number';
                        } else if (value.isEmpty) {
                          return 'Please enter a number';
                        }
                        return null;
                      },
                      keyboardType: TextInputType.number,
                      decoration: const InputDecoration(labelText: 'kcal'),
                      onSaved: (value) {
                        newRecipe = Recipe(
                          title: data['title'],
                          description: data['description'],
                          id: newRecipe.id,
                          ingredients: data['ingredients'],
                          steps: data['steps'],
                          imageUrl: data['imageUrl'],
                          creatorId: data['creatorId'],
                          kcal: int.parse(value!),
                          p: newRecipe.p,
                          c: newRecipe.c,
                          f: newRecipe.f,
                          servings: newRecipe.servings,
                        );
                      },
                    ),
                  ),
                  NutritionRow(
                    'Protein',
                    TextFormField(
                      initialValue:
                          data['id'] == '' ? '0' : data['p'],
                      validator: (value) {
                        if (int.parse(value!) < 0) {
                          return 'Please enter a valid number';
                        } else if (value.isEmpty) {
                          return 'Please enter a number';
                        }
                        return null;
                      },
                      keyboardType: TextInputType.number,
                      decoration: const InputDecoration(labelText: 'protein'),
                      onSaved: (value) {
                        newRecipe = Recipe(
                          creatorId: data['creatorId'],
                          title: data['title'],
                          description: data['description'],
                          id: newRecipe.id,
                          ingredients: data['ingredients'],
                          steps: data['steps'],
                          imageUrl: data['imageUrl'],
                          kcal: newRecipe.kcal,
                          p: int.parse(value!),
                          c: newRecipe.c,
                          f: newRecipe.f,
                          servings: newRecipe.servings,
                        );
                      },
                    ),
                  ),
                  NutritionRow(
                    'Carbohydrates',
                    TextFormField(
                      initialValue:
                          data['id'] == '' ? '0' : data['c'],
                      validator: (value) {
                        if (int.parse(value!) < 0) {
                          return 'Please enter a valid number';
                        } else if (value.isEmpty) {
                          return 'Please enter a number';
                        }
                        return null;
                      },
                      keyboardType: TextInputType.number,
                      decoration:
                          const InputDecoration(labelText: 'Carbohydrates'),
                      onSaved: (value) {
                        newRecipe = Recipe(
                          creatorId: data['creatorId'],
                          title: data['title'],
                          description: data['description'],
                          id: newRecipe.id,
                          ingredients: data['ingredients'],
                          steps: data['steps'],
                          imageUrl: data['imageUrl'],
                          kcal: newRecipe.kcal,
                          p: newRecipe.p,
                          c: int.parse(value!),
                          f: newRecipe.f,
                          servings: newRecipe.servings,
                        );
                      },
                    ),
                  ),
                  NutritionRow(
                    'Fats',
                    TextFormField(
                      initialValue:
                          data['id'] == '' ? '0' : data['f'],
                      validator: (value) {
                        if (int.parse(value!) < 0) {
                          return 'Please enter a valid number';
                        } else if (value.isEmpty) {
                          return 'Please enter a number';
                        }
                        return null;
                      },
                      keyboardType: TextInputType.number,
                      decoration: const InputDecoration(labelText: 'Fats'),
                      onSaved: (value) {
                        newRecipe = Recipe(
                          creatorId: data['creatorId'],
                          title: data['title'],
                          description: data['description'],
                          id: newRecipe.id,
                          ingredients: data['ingredients'],
                          steps: data['steps'],
                          imageUrl: data['imageUrl'],
                          kcal: newRecipe.kcal,
                          p: newRecipe.p,
                          c: newRecipe.c,
                          f: int.parse(value!),
                          servings: newRecipe.servings,
                        );
                      },
                    ),
                  ),
                  NutritionRow(
                    'Servings',
                    TextFormField(
                      initialValue: data['id'] == '' ? '0' : data['servings'],
                      validator: (value) {
                        if (int.parse(value!) < 0) {
                          return 'Please enter a valid number';
                        } else if (value.isEmpty) {
                          return 'Please enter a number';
                        }
                        return null;
                      },
                      keyboardType: TextInputType.number,
                      decoration: const InputDecoration(labelText: 'Servings'),
                      onSaved: (value) {
                        newRecipe = Recipe(
                          title: data['title'],
                          description: data['description'],
                          id: newRecipe.id,
                          ingredients: data['ingredients'],
                          imageUrl: data['imageUrl'],
                          steps: data['steps'],
                          creatorId: data['creatorId'],
                          kcal: newRecipe.kcal,
                          p: newRecipe.p,
                          c: newRecipe.c,
                          f: newRecipe.f,
                          servings: int.parse(value!),
                        );
                      },
                    ),
                  ),
                  Container(
                    height: 50,
                  ),
                  ElevatedButton(
                    style: Theme.of(context)
                        .elevatedButtonTheme
                        .style!
                        .copyWith(
                          shape:
                              MaterialStateProperty.all<RoundedRectangleBorder>(
                            RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(30),
                              side: BorderSide(
                                color: Theme.of(context).primaryColor,
                              ),
                            ),
                          ),
                          fixedSize: MaterialStateProperty.all<Size>(
                            Size(
                              deviceSize.width * 0.6,
                              deviceSize.height * 0.07,
                            ),
                          ),
                        ),
                    onPressed: saveForm,
                    child: Text(
                      'DONE',
                      style: Theme.of(context)
                          .textTheme
                          .headline2!
                          .copyWith(fontSize: 20),
                    ),
                  ),
                  const SizedBox(
                    height: 10,
                  ),
                ],
              ),
            ),
    );
  }
}

class NutritionRow extends StatelessWidget {
  final String value;
  Widget child;
  NutritionRow(this.value, this.child);

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Card(
          color: Colors.white,
          elevation: 20,
          margin: const EdgeInsets.symmetric(horizontal: 15, vertical: 5),
          child: Container(
            width: MediaQuery.of(context).size.width,
            height: MediaQuery.of(context).size.height * 0.1,
            padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 2),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                Text(
                  value,
                  style: Theme.of(context)
                      .textTheme
                      .headline5!
                      .copyWith(fontSize: 20),
                ),
                Expanded(
                  child: Container(),
                ),
                SizedBox(
                  child: child,
                  width: 100,
                ),
              ],
            ),
          ),
        ),
        const SizedBox(
          height: 20,
        ),
      ],
    );
  }
}

CodePudding user response:

You cant set a value of TextField to an int but what you can do is that you can set the initial value as an string to the text field

TextFormField(
                    initialValue: data['id'] == ''
                      ? '0'
                      : '${data['kcal']}',
                  validator: (value) {
                    if (int.parse(value!) <= 0) {
                      return 'Please enter a valid number';
                    } else if (value.isEmpty) {
                      return 'Please enter a number';
                    }
                    return null;
                  },
                  keyboardType: TextInputType.number,
                  decoration: const InputDecoration(labelText: 'kcal'),
                  onSaved: (value) {
                    newRecipe = Recipe(
                      title: data['title'],
                      description: data['description'],
                      id: newRecipe.id,
                      ingredients: data['ingredients'],
                      steps: data['steps'],
                      imageUrl: data['imageUrl'],
                      creatorId: data['creatorId'],
                      kcal: int.parse(value!),
                      p: newRecipe.p,
                      c: newRecipe.c,
                      f: newRecipe.f,
                      servings: newRecipe.servings,
                    );
                  },
                ),

then parse it as an int if you want an output of int

CodePudding user response:

you are trying to assign an integer to a string.

To fix this do this wherever needed:

initialValue: data['id'] == ''
                          ? '0'
                          : data['kcal'].toString(),

You have this error because seem's to be an integer and you try to affect this integer to an string value.

toString method will convert you int to String.

  • Related