error 'formDataList' isn't defined. in flutter app

29 views Asked by At

I am working on a flutter inventory surplus app that takes the inputs that are entered on the form stores them in local storage and then redirects to a summarypage where it loads the localstorage data into DataColumns

I have one error on my form page and here it is:

[{
    "resource": "/c:/Users/cdebrodie/Documents/apps/surplus/surplus/lib/main.dart",
    "owner": "_generated_diagnostic_collection_name_#0",
    "code": {
        "value": "undefined_named_parameter",
        "target": {
            "$mid": 1,
            "external": "https://dart.dev/diagnostics/undefined_named_parameter",
            "path": "/diagnostics/undefined_named_parameter",
            "scheme": "https",
            "authority": "dart.dev"
        }
    },
    "severity": 8,
    "message": "The named parameter 'formDataList' isn't defined.\nTry correcting the name to an existing named parameter's name, or defining a named parameter with the name 'formDataList'.",
    "source": "dart",
    "startLineNumber": 43,
    "startColumn": 81,
    "endLineNumber": 43,
    "endColumn": 93
}]

here is the main.dart code

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:surplus/summary';

void main() => runApp(MaterialApp(home: MyApp(),));

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<MyCustomForm> forms = [];
  String? _selectedSchool;
  final List<String> _schools = [
    'Gentry Middle School',
    'Oakland Middle School',
    'Jefferson Middle School',
    'West Middle School',
  ];

  List<String> formDataList = []; // Declare formDataList here

  @override
  void initState() {
    super.initState();
    forms.add(MyCustomForm(formDataList: formDataList, onCpsNumberTyped: addNewForm));
  }

  void addNewForm() {
    setState(() {
      forms.add(MyCustomForm(formDataList: formDataList, onCpsNumberTyped: addNewForm));
    });
  }

  void reviewData(BuildContext context) async {
    final prefs = await SharedPreferences.getInstance();
    formDataList.clear(); // Clear formDataList before adding new data
    forms.forEach((form) {
      formDataList.add('${_selectedSchool ?? 'No School Selected'}|${form.cpsNumber}|${form.itemDescription}|${form.selectedReason}');
    });
    await prefs.setStringList('formData', formDataList);
    Navigator.push(context, MaterialPageRoute(builder: (context) => SummaryPage(formDataList: formDataList)));
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Navigator(
        onGenerateRoute: (settings) {
          return MaterialPageRoute(builder: (context) => Scaffold(
            appBar: AppBar(
              title: Text('Dynamic Form Addition'),
            ),
            body: Column(
              children: [
                Padding(
                  padding: EdgeInsets.all(16.0),
                  child: DropdownButtonFormField<String>(
                    value: _selectedSchool,
                    decoration: InputDecoration(
                      labelText: 'Select School',
                      border: OutlineInputBorder(),
                    ),
                    onChanged: (String? newValue) {
                      setState(() {
                        _selectedSchool = newValue;
                      });
                    },
                    items: _schools.map<DropdownMenuItem<String>>((String value) {
                      return DropdownMenuItem<String>(
                        value: value,
                        child: Text(value),
                      );
                    }).toList(),
                  ),
                ),
                Expanded(
                  child: ListView.builder(
                    itemCount: forms.length,
                    itemBuilder: (context, index) => forms[index],
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.symmetric(vertical: 16.0),
                  child: ElevatedButton(
                    onPressed: () => reviewData(context),
                    child: Text('REVIEW'),
                  ),
                ),
              ],
            ),
          ));
        },
      ),
    );
  }
}

class MyCustomForm extends StatefulWidget {
  final VoidCallback onCpsNumberTyped;
  final List<String> formDataList; // Add formDataList as a named parameter

  MyCustomForm({required this.onCpsNumberTyped, required this.formDataList}); // Modify the constructor

  @override
  _MyCustomFormState createState() => _MyCustomFormState(formDataList: formDataList); // Pass formDataList to state

  String get cpsNumber => '';
  String get itemDescription => '';
  String get selectedReason => '';
}

class _MyCustomFormState extends State<MyCustomForm> {
  final TextEditingController _cpsNumberController = TextEditingController();
  final TextEditingController _itemDescriptionController = TextEditingController();
  List<String> formDataList; // Remove declaration here

  _MyCustomFormState({required this.formDataList}); // Add constructor to receive formDataList

  String? selectedReason;
  bool isFirstTime = true;

  final List<String> _reasonsForSurplus = [
    'Obsolete Equipment',
    'Replacement',
    'Damage',
    'Others',
  ];

  String get cpsNumber => _cpsNumberController.text;
  String get itemDescription => _itemDescriptionController.text;

  @override
  void initState() {
    super.initState();
    _cpsNumberController.addListener(() {
      if (isFirstTime && _cpsNumberController.text.isNotEmpty) {
        widget.onCpsNumberTyped();
        isFirstTime = false;
      }
    });
  }

  @override
  void dispose() {
    _cpsNumberController.dispose();
    _itemDescriptionController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Card(
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              TextFormField(
                controller: _cpsNumberController,
                decoration: InputDecoration(
                  labelText: 'CPS Number',
                  border: OutlineInputBorder(),
                ),
                onChanged: (newValue) {
                  // Add the form data to the list when CPS Number is changed
                  formDataList.add('${newValue ?? ''}|${_itemDescriptionController.text}|$selectedReason');
                },
              ),
              SizedBox(height: 24.0),
              TextFormField(
                controller: _itemDescriptionController,
                decoration: InputDecoration(
                  labelText: 'Item Description',
                  border: OutlineInputBorder(),
                ),
                maxLines: null,
              ),
              SizedBox(height: 24.0),
              DropdownButtonFormField<String>(
                value: selectedReason,
                decoration: InputDecoration(
                  labelText: 'Reason for Surplus',
                  border: OutlineInputBorder(),
                ),
                onChanged: (String? newValue) {
                  setState(() {
                    selectedReason = newValue;
                  });
                },
                items: _reasonsForSurplus.map<DropdownMenuItem<String>>((String value) {
                  return DropdownMenuItem<String>(
                    value: value,
                    child: Text(value),
                  );
                }).toList(),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

EDIT EDIT!!! HERE is the new code:

    import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:surplus/summary';

void main() => runApp(MaterialApp(home: MyApp(),));

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<MyCustomForm> forms = [];
  String? _selectedSchool;
  final List<String> _schools = [
    'Gentry Middle School',
    'Oakland Middle School',
    'Jefferson Middle School',
    'West Middle School',
  ];

  List<String> formDataList = []; // Declare formDataList here

  @override
  void initState() {
    super.initState();
    forms.add(MyCustomForm(formDataList: formDataList, onCpsNumberTyped: addNewForm));
  }

  void addNewForm() {
    setState(() {
      forms.add(MyCustomForm(formDataList: formDataList, onCpsNumberTyped: addNewForm));
    });
  }

  void reviewData(BuildContext context) async {
    final prefs = await SharedPreferences.getInstance();
    formDataList.clear(); // Clear formDataList before adding new data
    forms.forEach((form) {
      formDataList.add('${_selectedSchool ?? 'No School Selected'}|${form.cpsNumber}|${form.itemDescription}|${form.selectedReason}');
    });
    await prefs.setStringList('formData', formDataList);
    Navigator.push(context, MaterialPageRoute(builder: (context) => SummaryPage(formDataList: formDataList))); // Pass formDataList here
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Navigator(
        onGenerateRoute: (settings) {
          return MaterialPageRoute(builder: (context) => Scaffold(
            appBar: AppBar(
              title: Text('Dynamic Form Addition'),
            ),
            body: Column(
              children: [
                Padding(
                  padding: EdgeInsets.all(16.0),
                  child: DropdownButtonFormField<String>(
                    value: _selectedSchool,
                    decoration: InputDecoration(
                      labelText: 'Select School',
                      border: OutlineInputBorder(),
                    ),
                    onChanged: (String? newValue) {
                      setState(() {
                        _selectedSchool = newValue;
                      });
                    },
                    items: _schools.map<DropdownMenuItem<String>>((String value) {
                      return DropdownMenuItem<String>(
                        value: value,
                        child: Text(value),
                      );
                    }).toList(),
                  ),
                ),
                Expanded(
                  child: ListView.builder(
                    itemCount: forms.length,
                    itemBuilder: (context, index) => forms[index],
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.symmetric(vertical: 16.0),
                  child: ElevatedButton(
                    onPressed: () => reviewData(context),
                    child: Text('REVIEW'),
                  ),
                ),
              ],
            ),
          ));
        },
      ),
    );
  }
}

class MyCustomForm extends StatefulWidget {
  final VoidCallback onCpsNumberTyped;
  final List<String> formDataList; // Add formDataList as a parameter

  MyCustomForm({required this.onCpsNumberTyped, required this.formDataList}); // Modify the constructor

  @override
  _MyCustomFormState createState() => _MyCustomFormState(formDataList: formDataList); // Pass formDataList to state

  String get cpsNumber => '';
  String get itemDescription => '';
  String get selectedReason => '';
}

class _MyCustomFormState extends State<MyCustomForm> {
  final TextEditingController _cpsNumberController = TextEditingController();
  final TextEditingController _itemDescriptionController = TextEditingController();
  List<String> formDataList; // Remove declaration here

  _MyCustomFormState({required this.formDataList}); // Add constructor to receive formDataList

  String? selectedReason;
  bool isFirstTime = true;

  final List<String> _reasonsForSurplus = [
    'Obsolete Equipment',
    'Replacement',
    'Damage',
    'Others',
  ];

  String get cpsNumber => _cpsNumberController.text;
  String get itemDescription => _itemDescriptionController.text;

  @override
  void initState() {
    super.initState();
    _cpsNumberController.addListener(() {
      if (isFirstTime && _cpsNumberController.text.isNotEmpty) {
        widget.onCpsNumberTyped();
        isFirstTime = false;
      }
    });
  }

  @override
  void dispose() {
    _cpsNumberController.dispose();
    _itemDescriptionController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Card(
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              TextFormField(
                controller: _cpsNumberController,
                decoration: InputDecoration(
                  labelText: 'CPS Number',
                  border: OutlineInputBorder(),
                ),
                onChanged: (newValue) {
                  // Add the form data to the list when CPS Number is changed
                  formDataList.add('${newValue}|${_itemDescriptionController.text}|$selectedReason');
                },
              ),
              SizedBox(height: 24.0),
              TextFormField(
                controller: _itemDescriptionController,
                decoration: InputDecoration(
                  labelText: 'Item Description',
                  border: OutlineInputBorder(),
                ),
                maxLines: null,
              ),
              SizedBox(height: 24.0),
              DropdownButtonFormField<String>(
                value: selectedReason,
                decoration: InputDecoration(
                  labelText: 'Reason for Surplus',
                  border: OutlineInputBorder(),
                ),
                onChanged: (String? newValue) {
                  setState(() {
                    selectedReason = newValue;
                  });
                },
                items: _reasonsForSurplus.map<DropdownMenuItem<String>>((String value) {
                  return DropdownMenuItem<String>(
                    value: value,
                    child: Text(value),
                  );
                }).toList(),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

EDIT Here is the new errors I am getting:

The named parameter 'formDataList' isn't defined.
Try correcting the name to an existing named parameter's name, or defining a named parameter with the name 'formDataList'.

I am new to flutter so any help would be amazing!!!

Thanks in advance!

1

There are 1 answers

7
Emsil Neumann On BEST ANSWER

The error you're encountering seems to be due to a missing declaration of the formDataList variable in your MyCustomForm class.

In your MyCustomForm class, add the declaration of formDataList as a named parameter in the constructor. esentially you must modify the constructor to accept formDataList. you shoul pass formDataList to the state class _MyCustomFormState. Try to update your code for your MyCustomForm class:

class MyCustomForm extends StatefulWidget {
final VoidCallback onCpsNumberTyped;
final List<String> formDataList; // Add formDataList as a named parameter

MyCustomForm({required this.onCpsNumberTyped, required this.formDataList}); // Modify the constructor

@override
_MyCustomFormState createState() => _MyCustomFormState(formDataList: formDataList); // Pass formDataList to state

 String get cpsNumber => '';
 String get itemDescription => '';
 String get selectedReason => '';
}

and also in the _MyCustomFormState class, you must remove the declaration of formDataList. your code should resolve the error related to the undefined named parameter formDataList, where i see.

////////////// >>>> Edit after comment: this is form class

class MyCustomForm extends StatefulWidget {
final VoidCallback onCpsNumberTyped;
final List<String> formDataList; // Add formDataList as a named parameter

MyCustomForm({required this.onCpsNumberTyped, required this.formDataList}); // Modify the constructor

@override
_MyCustomFormState createState() =>  _MyCustomFormState(formDataList: formDataList); // Pass formDataList to state

}

and _MyCustomFormState class can be :

class _MyCustomFormState extends State<MyCustomForm> {
 final TextEditingController _cpsNumberController = TextEditingController();
 final TextEditingController _itemDescriptionController = TextEditingController();
 List<String> formDataList; // Remove declaration here

 _MyCustomFormState({required this.formDataList}); // Add constructor to receive formDataList

  String? selectedReason;
  bool isFirstTime = true;
  // ... your codes 
   }

////////////////////// SECOND EDIT;

make sure everything is properly connected.

firstly, make that the cpsNumber getter was defined within the _MyCustomFormState class, not directly within the MyCustomForm class. The same applies to other getters like itemDescription and selectedReason.

amd then, make sure that formDataList is being accessed correctly within the MyCustomForm widget. Since you're passing it as a parameter to the state class, you should reference it via widget.formDataList within the state class. (stateful and stateless classes are NOT same things)

class _MyCustomFormState extends State<MyCustomForm> {
final TextEditingController _cpsNumberController = TextEditingController();
final TextEditingController _itemDescriptionController = TextEditingController();
List<String> formDataList;

_MyCustomFormState({required this.formDataList});

String get cpsNumber => _cpsNumberController.text;
String get itemDescription => _itemDescriptionController.text;
String get selectedReason => selectedReason;

// rest of your code 
}

oyu must access formDataList using widget.formDataList within the MyCustomForm widget:

class MyCustomForm extends StatefulWidget {
final VoidCallback onCpsNumberTyped;
final List<String> formDataList;

MyCustomForm({required this.onCpsNumberTyped, required this.formDataList});

 @override
 _MyCustomFormState createState() => _MyCustomFormState(formDataList: formDataList);
 }

after editing your code, if you're still facing issues, double-check the usage of getters and parameters across your classes.