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!
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:
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
}
and _MyCustomFormState class can be :
////////////////////// 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)
oyu must access formDataList using widget.formDataList within the MyCustomForm widget:
after editing your code, if you're still facing issues, double-check the usage of getters and parameters across your classes.