add multiple dropdown value to a List in flutter - flutter

In my flutter app I've created a dropdown. initially there is only one dropdown but the user can add more. the items of these dropdowns are the same. but the selected results has to be different. but my code is returning the last selected value. so how can I add it on list?
Model
class DropModel {
String? selected;
DropModel({this.selected});
setData(list) {
for (int i = 0; i < list.length; i++) {
selected = list;
}
}
}
initialize
List<String>? selCat;
DropModel selDrop = DropModel();
dropdown widget
DropdownButtonFormField2 _generatedDropDown(
List<String> category, String? selected, int index) {
final group = _GroupControllers();
return DropdownButtonFormField2(
decoration: InputDecoration(
isDense: true,
contentPadding: EdgeInsets.zero,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
),
),
isExpanded: true,
hint: const Text(
'Select Category',
style: TextStyle(fontSize: 14),
),
icon: const Icon(
Icons.arrow_drop_down,
color: Colors.black45,
),
iconSize: 30,
buttonHeight: 60,
buttonPadding: const EdgeInsets.only(left: 20, right: 10),
items: category
.map((item) => DropdownMenuItem<String>(
value: item,
child: Text(
item,
style: const TextStyle(
fontSize: 14,
),
),
))
.toList(),
validator: (value) {
if (value == null) {
return 'Please select Catagory.';
}
},
onChanged: (value) {
//Do something when changing the item if you want.
setState(() {
// selDrop.setData(value.toString());
selected = value.toString();
selDrop.selected = selected;
selCat!.insert(index, selected.toString());
});
},
onSaved: (value) {
//selDrop.setData(value.toString());
selected = value.toString();
selDrop.selected = selected;
selCat!.insert(index, selected.toString());
},
);
}
result looped
print(".................${selDrop.selected}"); // returns the last added/ selected value
print(".................${selCat}"); //returns null
the traditional List returns null and the model returns the last added/selected value. how can i add multiple dropdown selected values to a List? each has different values. in a textfield I could create dynamic TextEditingController but how can I manage dropdowns

Related

from dropdownmenu to dropdownsearch in flutter

I was using normal dropdown menu in my project with small amount of data fetched from my api, but now i have menu which could reach hundred of values and make it hard to select an item.
That's why i wanted to use DropDownSearch but instead i get an error
Normal dropdown code which works very fine
DropdownButton(
showSearchBox: true,
showSelectedItem: true,
items: data3.map((item) {
return new DropdownMenuItem(
child: Text(item['first_name']+" "+ item['last_name']),
value: item['emp_code'].toString(),
);
}).toList(),
onChanged: (newVal) {
setState(() {
_mySelection3 = newVal.toString();
});
},
value: _mySelection3,
),
data3 = [{emp_code: 111, first_name: adnen, last_name: hamouda}, {emp_code: 666, first_name: ahmed, last_name: ahmed 99}....
this is the result: normal dropdown
But when i tried to convert it to dropDownSearch i got this result: search dropdown
I want to show the first_name and last_name like the normal dropdown but save the value of their 'emp_code' which i will be using in another api later. How can i fix it ?
DropdownSearch(
mode: Mode.DIALOG,
showSearchBox: true,
items: data3.map((item) {
return new DropdownMenuItem(
child: Text(item['first_name']+" "+ item['last_name']),
value: item['emp_code'].toString(),
);
}).toList(),
onChanged: (newVal) {
setState(() {
print(data3);
_mySelection3 = newVal.toString();
});
},
selectedItem: _mySelection3,
),
Here is the way I found to use searchable dropdown lists.
I tried dropdown_search package at first, but it seems the documentation and examples related with the latest version (5.0.2) are depreciated.
Later on, I moved to dropdown_button2 and I am happy the way the DropdownButtonFormField2 was implemented, because it is very similar which I have done to the flutter DropdownButtonFormField implementation, so far.
Have a look at the Flutter bundled DropdownButtonFormField example:
return DropdownButtonFormField<SetorTemp>(
decoration: const InputDecoration(
labelText: 'Setor institucional'),
isExpanded: true,
icon: const Icon(Icons.arrow_downward),
items: snapshot.data!
.map((SetorTemp rtItem) =>
DropdownMenuItem<SetorTemp>(
value: rtItem,
child: Text(
'${rtItem.nome} (${rtItem.sigla})',
softWrap: true,
),
))
.toList(),
hint: Text(
'${selectedSetorTemp.nome} (${selectedSetorTemp.sigla})'),
onChanged: (SetorTemp? newValue) {
setState(() {
// do your logic here!
selectedSetorTemp = newValue;
});
},
);
And the DropdownButtonFormField2 using dropdown_button2 package
return DropdownButtonFormField2<SetorTemp>(
decoration: const InputDecoration(
labelText: 'Setor institucional'),
isExpanded: true,
icon: const Icon(Icons.arrow_downward),
items: snapshot.data!
.map((SetorTemp rtItem) =>
DropdownMenuItem<SetorTemp>(
value: rtItem,
child: Text(
'${rtItem.nome} (${rtItem.sigla})',
softWrap: true,
),
))
.toList(),
hint: Text(
'${selectedSetorTemp.nome} (${selectedSetorTemp.sigla})'),
onChanged: (SetorTemp? newValue) {
setState(() {
// Do your logic here!
selectedSetorTemp = newValue;
});
},
// Search implementation using dropdown_button2 package
searchController: searchContentSetor,
searchInnerWidget: Padding(
padding: const EdgeInsets.only(
top: 8,
bottom: 4,
right: 8,
left: 8,
),
child: TextFormField(
controller: searchContentSetor,
decoration: InputDecoration(
isDense: false,
contentPadding: const EdgeInsets.symmetric(
horizontal: 8,
vertical: 8,
),
labelText: 'Setor institucional',
hintText: 'Parte do nome do setor...',
counterText: '',
hintStyle: const TextStyle(fontSize: 16),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
),
),
),
searchMatchFn: (rtItem, searchValue) {
return (rtItem.value.nome
.toLowerCase()
.contains(searchValue.toLowerCase()));
},
//This to clear the search value when you close the menu
onMenuStateChange: (isOpen) {
if (!isOpen) {
searchContentSetor.clear();
}
},
);
They are similar at first:
However, after clicking they will show their differences from the initial implementation:
To the dropdown_button2 package:
The selectedSetorTemp variable is of the type SetorTemp and the model I have used is:
class SetorTemp {
final int id;
final String? nome;
final String? sigla;
SetorTemp({required this.id, this.nome, this.sigla});
factory SetorTemp.fromJson(Map<String, dynamic> json) {
return SetorTemp(
id: json['id'] as int,
nome: json['nome'] as String,
sigla: json['sigla'] as String,
);
}
Map<String, dynamic> toJson() => {
'nome': nome,
'sigla': sigla,
};
}

# Flutter Adding Two Fields Result

I have created a List that stores and save multiple values and then sum it.
Now I have created another text field that stores price I wanna multiple this text field value with the list result but getting error it display null please help me out thankyou.
This is the code How I am doing sum of List
List<String> items = <String>[];
int getTotal() {
return items.fold(0, (total, item) {
int? price = int.tryParse(item);
if (price != null) {
num = total + price;
return (num);
// return total + price;
} else {
return total;
}
});
}
List
Column(
children: [
...List.generate(
items.length,
(index) => TextFormField(
keyboardType: TextInputType.number,
onChanged: (value) => items[index] = value,
decoration: InputDecoration(
hintText: items[index],
labelStyle: TextStyle(fontSize: 20.0),
border: OutlineInputBorder(),
suffixIcon: IconButton(
icon: const Icon(Icons.delete, color: Colors.red),
onPressed: () {
items.remove(items[index]);
setState(() {});
},
),
),
),
),
Then I am creating another field where I am getting price
This is how I am creating another text field which value I wanna multiply with the above list value.
Container(
margin: EdgeInsets.symmetric(vertical: 10.0),
child: TextFormField(
keyboardType: TextInputType.number,
autofocus: false,
decoration: InputDecoration(
labelText: 'Total Price: ',
labelStyle: TextStyle(fontSize: 20.0),
border: OutlineInputBorder(),
errorStyle:
TextStyle(color: Colors.redAccent, fontSize: 15),
),
controller: amountController,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please Enter Price';
}
return null;
},
),
This is how should your sum function should looks like:
int getMultiply() {
return multiply.fold(0, (int total, element) {
final price = int.tryParse(element);
// if price can't be parsed returns total
return total + (price ?? 0);
});
}
This is an example of text field's controller that updates global state every time it's value can be parsed to int and not equals to 0:
final TextEditingController amountController = TextEditingController()
..addListener(() {
final value = int.tryParse(amountController.text) ?? 0;
final result = value * getMultiply();
if (result > 0) {
setState(() {
// some global field that presents requested value
multiplyResult = result;
});
}
});
List of items:
Column(children: [
...List.generate(
items.length,
(index) => TextFormField(
keyboardType: TextInputType.number,
onChanged: (value) => setState(() { items[index] = value; }),
decoration: InputDecoration(
hintText: items[index],
labelStyle: TextStyle(fontSize: 20.0),
border: OutlineInputBorder(),
suffixIcon: IconButton(
icon: const Icon(Icons.delete, color: Colors.red),
onPressed: () => setState(() {
items.remove(items[index]);
}),
),
),
),
),

Flutter how to set the value of the dropdown button programmatically

I m new to flutter, need help to set the value of the DropdownButton programmatically.
The value is from textfield. Once i click it, it will set the value at the dropdownbutton automatically.
Widget _districtListContainer() {
return Container(
width: 360.0,
child: new InputDecorator(
decoration: InputDecoration(
suffixIcon: new Icon(
Icons.search,
color: Colors.blue[700],
),
labelText: 'Select District',
labelStyle: TextStyle(fontSize: 12.0)),
isEmpty: _selectedDistrict == null,
child: new DropdownButtonHideUnderline(
child: new DropdownButton<District>(
value: _selectedDistrict,
isDense: true,
isExpanded: false,
onChanged: (District newValue) {
setState(() {
_selectedDistrict = newValue;
});
},
items: _listDistrict?.map((District value) {
return new DropdownMenuItem<District>(
value: value,
child: new Text(
value.district != null ? value.district : '',
style: new TextStyle(fontSize: 11.0),
),
);
})?.toList() ??
[],
),
),
),
margin: EdgeInsets.only(bottom: 10.0));
}
thanks
First Of All, Add the data into the list[] From the TextFormfield then retrieve the list into DropDownButton item.
Also, Make Sure, DropDown Button List Display Textformfield data insert activity could not be able to update simultaneously.

Flutter onChanged: not triggering method to read textfield content

I have a form where users capture information on multiple textfields. Within the Onchange:, I can see that there's activity every time the user types something on the textfield. However, when I call a method to read the textfield content, the method is not being fired. For example, I call the updateFirstName() method within the OnChange: within the nameController textfield. The method doesn't fire and the App fails when I press Save because the FirstName field is null. Any reason why the updateFirstName method on my code below is not being called? I'm new to Flutter so I might be missing something basic.
import 'dart:ffi';
import 'package:flutter/material.dart';
import '../widgets/main_drawer.dart';
import '../utils/database_helper.dart';
import '../models/customer.dart';
import 'package:intl/intl.dart';
class CustomerDetailsScreen extends StatefulWidget {
static const routeName = '/customer-details';
#override
_CustomerDetailsScreenState createState() => _CustomerDetailsScreenState();
}
class _CustomerDetailsScreenState extends State<CustomerDetailsScreen> {
//Define editing controllers for all the text fields
TextEditingController nameController = TextEditingController();
TextEditingController surnameController = TextEditingController();
TextEditingController cellphoneController = TextEditingController();
TextEditingController emailController = TextEditingController();
//Connecting to the database
DatabaseHelper helper = DatabaseHelper();
//Define some variables
String appBarTitle;
Customer customer; //This is the Customer Model
/*
String sFirstName;
String sSurname;
String sCellNumber;
String sEmailAddress;
String sCompanyName = '-';
*/
var _formKey = GlobalKey<FormState>();
//Method to validate e-mail address
bool validateEmail(String value) {
Pattern pattern =
r'^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
RegExp regex = new RegExp(pattern);
return (!regex.hasMatch(value)) ? false : true;
}
#override
Widget build(BuildContext context) {
TextStyle textStyle = Theme.of(context).textTheme.title;
//Populate the text fields
//nameController.text = customer.sFirstName;
//surnameController.text = customer.sSurname;
//cellphoneController.text = customer.sCellNumber;
//emailController.text = customer.sEmailAddress;
return Scaffold(
appBar: AppBar(
title: Text('Edit Customer'),
),
body: GestureDetector(
//Gesture detector wrapped the entire body so we can hide keyboard \
// when user clicks anywhere on the screen
behavior: HitTestBehavior.opaque,
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
},
child: Form(
key: _formKey,
child: Padding(
padding: EdgeInsets.only(top: 15.0, left: 10.0, right: 10.0),
child: ListView(
children: <Widget>[
//First Element - Name
Padding(
padding: EdgeInsets.only(top: 15.0, bottom: 15.0),
child: TextFormField(
controller: nameController,
style: textStyle,
textCapitalization: TextCapitalization.words,
validator: (String value) {
if (value.isEmpty) {
return 'Please enter your name';
}
return null;
},
onChanged: (value) {
debugPrint('Something changed on the Name Text Field');
updateFirstName();
},
decoration: InputDecoration(
labelText: 'Name',
labelStyle: textStyle,
errorStyle:
TextStyle(color: Colors.redAccent, fontSize: 15.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0),
),
),
),
),
//Second Element - Surname
Padding(
padding: EdgeInsets.only(top: 15.0, bottom: 15.0),
child: TextFormField(
controller: surnameController,
style: textStyle,
textCapitalization: TextCapitalization.words,
validator: (String value) {
if (value.isEmpty) {
return 'Please enter your surname';
}
return null;
},
onChanged: (value) {
debugPrint('Something changed on the Surname Text Field');
updateSurname();
},
decoration: InputDecoration(
labelText: 'Surname',
labelStyle: textStyle,
errorStyle:
TextStyle(color: Colors.redAccent, fontSize: 15.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0),
),
),
),
),
//Third Element - Cellphone
Padding(
padding: EdgeInsets.only(top: 15.0, bottom: 15.0),
child: TextFormField(
controller: cellphoneController,
style: textStyle,
keyboardType: TextInputType.number,
validator: (String value) {
if (value.isEmpty) {
return 'Please enter your cellphone number';
} else {
if (value.length < 10)
return 'Cell number must be at least 10 digits';
}
return null;
},
onChanged: (value) {
debugPrint(
'Something changed on the Cellphone Text Field');
updateCellNumber();
},
decoration: InputDecoration(
labelText: 'Cellphone',
labelStyle: textStyle,
errorStyle:
TextStyle(color: Colors.redAccent, fontSize: 15.0),
hintText: 'Enter Cell Number e.g. 0834567891',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0),
),
),
),
),
//Fourth Element - Email Address
Padding(
padding: EdgeInsets.only(top: 15.0, bottom: 15.0),
child: TextFormField(
controller: emailController,
style: textStyle,
keyboardType: TextInputType.emailAddress,
validator: (String value) {
if (value.isEmpty) {
return 'Please enter your e-mail address';
} else {
//Check if email address is valid.
bool validmail = validateEmail(value);
if (!validmail) {
return 'Please enter a valid e-mail address';
}
}
return null;
},
onChanged: (value) {
debugPrint(
'Something changed on the Email Address Text Field');
updateEmailAddress();
},
decoration: InputDecoration(
labelText: 'E-mail',
labelStyle: textStyle,
errorStyle:
TextStyle(color: Colors.redAccent, fontSize: 15.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0),
),
),
),
),
//Fifth Element - Row for Save Button
Padding(
padding: EdgeInsets.only(top: 15.0, bottom: 15.0),
child: Row(
children: <Widget>[
Expanded(
child: RaisedButton(
color: Theme.of(context).primaryColorDark,
textColor: Theme.of(context).primaryColorLight,
child: Text(
'Save',
textScaleFactor: 1.5,
),
onPressed: () {
setState(() {
if (_formKey.currentState.validate()) {
debugPrint('Save button clicked');
//Call the Save method only if the validation is passed
_saveCustomerDetails();
}
});
}),
),
],
)),
],
),
),
),
),
);
}
//**********************Updating what is captured by the user on each text field******************/
//Update the sFirstName of the Customer model object
void updateFirstName() {
print('The updateFirstName was called');
customer.sFirstName = nameController.text;
}
//Update the sSurname of the Customer model object
void updateSurname() {
customer.sSurname = surnameController.text;
}
//Update the sCellNumber of the Customer model object
void updateCellNumber() {
customer.sCellNumber = cellphoneController.text;
}
//Update the sEmailAddress of the Customer model object
void updateEmailAddress() {
customer.sEmailAddress = emailController.text;
customer.sCompanyName = '-';
}
//**********************END - Updating what is captured by the user on each text field******************/
//**************************Saving to the Database*************************************/
void _saveCustomerDetails() async {
//moveToLastScreen();
//Update the dtUpdated of the Customer model with current time (Confirm that it is GMT)
print('Trying to save customer info was called');
customer.dtUpdated = DateFormat.yMMMd().format(DateTime.now());
print('Trying to save customer info was called - 2');
int result;
result = await helper.insertNewHumanCustomer(customer);
if (result != 0) {
//Saving was a Success
_showAlertDialog('Success', 'Customer details saved successfully');
print('The customer details were saved successfully');
} else {
//Saving was a Failure
print('FAILURE - The customer details failed to save');
_showAlertDialog('Failure', 'Oopsy.....something went wrong. Try again');
}
}
//*****Show Alert Popup message*****/
void _showAlertDialog(String title, String message) {
AlertDialog alertDialog = AlertDialog(
title: Text(title),
content: Text(message),
);
showDialog(context: context, builder: (_) => alertDialog);
}
//*****END - Show Alert Popup message*****/
//**************************Saving to the Database*************************************/
}

Multiple Dependent dropdown in flutter

I am trying to build multiple dependent dropdown on flutter. The second one depend on 1st one. here is the code to the dropdown I have implemented.
Container(
child: new DropdownButton<String>(
underline: SizedBox(
height: 1,
),
hint: new Text("Select Faculty"),
value: facultyId,
items: faculty.map((item) {
return new DropdownMenuItem(
child: new Text(item['name']),
value: item['id'].toString(),
);
}).toList(),
onChanged: (faculty == null)
? null
: (String newValue) {
setState(() {
filteredbatch.clear();
facultyId = newValue;
for (var item in allbatch) {
if (item['facultyId'].toString() == newValue){
filteredbatch.add(item);
disableBatch = false;
}
}
});
print(facultyId);
},
),
),
Container(
child: new DropdownButton<String>(
underline: SizedBox(
height: 1,
),
disabledHint: new Text("Select Faculty First"),
hint: Text("Select Batch"),
value: batchId,
onChanged: disableBatch
? null
: (String newValue) {
setState(() {
batchId = newValue;
disableSection = false;
});
print(batchId);
},
items: filteredbatch.map((item) {
return DropdownMenuItem(
child: Text(item['name']),
value: item['id'].toString(),
);
}).toList()),
),
Whenever I select one dropdown item from first one, it enables 2nd dropdown and lets me to select an item from that dropdown. And when I select an item from 2nd dropdown and go back to change first dropdown, it throws error that dropdown requires one item with respective value. 0 or 2 found. I am lost here. How do I resolve this error?
What is going on here is quite simple. Let's say "allbatch" has these values:
faculty: foo , which has batchids: foo1, foo2, foo3
faculty: bar , which has batchids: bar1, bar2, bar3.
When you select foo in the 1st dropdown a new "filteredbatch" is created and it only contains foo1,foo2,foo3. You then select foo3 in your 2nd dropdown and everything is still working fine...
BUT when you change your 1st dropdown to bar, then "filteredbatch" only contains:bar1, bar2, bar3 and your second dropdown value is still set to foo3 which can not be found in the newly generated "filteredbatch", and then you get that error you are seeing.
To fix this simply set batchId to null before changing the "filteredbatch" in your 1st dropdown onChanged method:
setState(() {
//fix
batchId = null;
//end of fix
filteredbatch.clear();
facultyId = newValue;
for (var item in allbatch) {
if (item['facultyId'].toString() == newValue){
filteredbatch.add(item);
disableBatch = false;
}
}
});
Your 2nd dropdown will revert back to hint text and the app user will have to select a new batchId.
If you have any more questions feel free to ask.
Flutter Dropdown Button FormField Dependent
List<String> dataList = ["A", "B", "C"];
List<String> dataListA = ["A1", "A2", "A3", "A4", "A5"];
List<String> dataListB = ["B1", "B2", "B3", "B4", "B5"];
List<String> dataListC = ["C1", "C2", "C3", "C4", "C5"];
String? valueItem;
List<String> listItem = [];
// DropdownButtonFormField
Container(
margin: const EdgeInsets.only(bottom: p20),
child: DropdownButtonFormField<String>(
decoration: InputDecoration(
labelText: 'Data list',
labelStyle: const TextStyle(),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0)),
contentPadding: const EdgeInsets.only(left: 5.0),),
value: valueItem,
isExpanded: true,
items: dataList.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),);
}).toSet().toList(),
onChanged: (value) {
setState(() {
valueItem= value!;
if (valueItem=="A") {
listItem= dataListA;
} else if (valueItem== "B") {
listItem= dataListB;
} else if (valueItem== "C") {
listItem= dataListC;
}
});
},
),
),
// Second DropdownButtonFormField
Container(
margin: const EdgeInsets.only(bottom: p20),
child: DropdownButtonFormField<String>(
decoration: InputDecoration(
labelText: 'List dependent',
labelStyle: const TextStyle(),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0)),
contentPadding: const EdgeInsets.only(left: 5.0),),
value: ListItem,
isExpanded: true,
items: listItem.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);}).toSet().toList(),
onChanged: (value) {
setState(() {
your_value = value!;
});
},
),
),