Hello I tried to create a dynamic dropdown with flutter. the request to end point returns the data successfully but the DropdownButtonFormField items array is reading zero. it is not getting the data at all. Please can any one help me?
Dropdown menu items variable:
List<DropdownMenuItem> _anchorLists = List<DropdownMenuItem>();
dynamic _selectedAnchor;
void initState() {
super.initState();
_getAnchorsByProvider();
}
The Function:
_getAnchorsByProvider() async {
try {
_prefs = await SharedPreferences.getInstance();
var _anchorService = AnchorService();
var result = await _anchorService
.getAnchorsByProviderId(_prefs.getInt('providerOid'));
var anchors = json.decode(result.body);
anchors.forEach((anchor) {
setState(() {
_anchorLists.add(DropdownMenuItem(
child: Text(anchor['acronym']),
value: anchor['oid'],
));
});
});
setState(() {
_isLoading = false;
});
} catch (e) {
setState(() {
_isLoading = false;
});
return e.toString();
}
}
The Dropdown
SizedBox(height: 20),
(_anchorLists.length > 0)?
DropdownButtonFormField(
value: _selectedAnchor,
items: _anchorLists,
hint: const Text('Select your Anchor'),
onChanged: (value) {
setState(() {
_selectedAnchor = value;
});
},
)
: Text('Loading'),
Result
Values of the json:
{
"oid": 1,
"acronym": "MAAN",
"contactAddress": "Abuja",
"idCardInstruction": null,
}
Because you are retrieving a json object (Map) and not a json list (List), forEach must iterate through key and value pairs, like so:
anchors.forEach((key, value) {
_anchorLists.add(DropdownMenuItem(
child: Text(value.toString()),
value: value.toString(),
));
});
I'm not sure of the specifics of your needs so tweak accordingly, but if you only wish to provide specific values, you can specify like so:
_anchorLists.addAll([anchors['acronym'], anchors['oid']]
.map((value) => DropdownMenuItem(
child: Text(value.toString()),
value: value.toString(),
)));
Related
i am trying to show category name and store category id in database but my categories id are not line by line
My Dropdown button
DropdownButton(
items: categoriesList.map((item) {
return DropdownMenuItem(
child: Text(item['name'].toString()), value: item['id'].toString());
}).toList(),
onChanged: (changedCategoryId) {
setState(() {
print(int.parse(changedCategoryId.toString()));
});
},
hint: Text(selectedCategory),
),
fetch data code
List categoriesList = [];
var selectedCategory = "Select Category";
#override
void initState() {
// TODO: implement initState
fetchCategories();
super.initState();
}
fetchCategories() async {
var fetchedCategoriesList =
await http.get(Uri.parse("${AppConfig.BASE_URL}categories"));
var decodedFetchedCategoriesList =
json.decode(fetchedCategoriesList.body)['data'];
setState(() {
categoriesList = decodedFetchedCategoriesList;
});
print(categoriesList);
}
onChanged: (changedCategoryId) { // this runType is Dropdow
final id = changedCategoryId['id'];
final name = changedCategoryId['name'];
},
you can store the id to database , and show the name on screen
I am trying to populate a drop down list from sql server in my flutter app.
I defined a List variable:
List data =List[];
which throws me error:
The name of the class 'List' can't be included in a list literal.
and i am gettin jason data as follows:
Future getDriverName() async{
SharedPreferences prefs = await SharedPreferences.getInstance();
var response = await http.post(Uri.parse(ROOT), body: {
"action": 'driverNames',
"id":prefs.getString('id')!
});
var driverNames = json.decode(response.body);
setState(() {
data=driverNames;
});
print(driverNames);
return "success";
}
and using in Dropdown button as follows:
DropdownButton(
items: data.map((list) {
return new DropdownMenuItem(
child: new Text(list['item_name']),
value: list['id'].toString(),
);
}).toList(),
onChanged: (newVal) {
setState(() {
selectedName = newVal.toString();
});
},
value: selectedName,
),
i am not able to understand the issue becouse i am new to flutter? please help.
Thanks in advance <3
This is because can't use List keyword when you are using a literal but you can define it into a different way like below :
with literal
List list = [];
with List keyword
List list = List.empty();
What I want to do is to load users and put them in a list. I am doing this with the function getUsers().
After that I want to load an Event (with fetchEvent()) which is a table with some dropdown menus.
My problem is that the users are sometimes not there when the event gets loaded. Thats why dropdown button is disabled.
I tried to solve this with using "then".
This is my initState:
void initState() {
besetzungsList.clear();
if (widget.eventId != null) {
getUsers().then((_) => fetchEvent());
} else
getUsers();
print(widget.eventId);
super.initState();
}
This is getUsers()
getUsers() async {
getCurrentUser();
usersStream = authBloc.getUsers();
usersStream.listen((allUsers) {
for (ApplicationUser user in allUsers) {
if (user.userRoleList.contains(team)) users.add(user.username);
}
});
}
fetchEvent() async {
...
dataTableRows.add(DataRow(
cells: [
DataCell(
Text(event.dienstMap["Aufgabe"][i]),
onTap: () {
removeRow(i);
},
),
DataCell(
Text(event.dienstMap["Zeit"][i]),
onTap: () {},
),
DataCell(
Text(event.dienstMap["Team"][i]),
onTap: () {},
),
DataCell((i > event.dienstMap["Besetzung"].length - 1 == true)
? DropDown(
hint: "Wählen",
users: users,
besetzungsListChanged: (String value) {
if (besetzungsList.length > 0) {
besetzungsList.removeAt(i);
}
besetzungsList.insert(i, value);
},
fromDropDown: (bool value) => fromDropDown = value,
)
: DropDown(
hint: event.dienstMap["Besetzung"][i],
users: users,
besetzungsListChanged: (String value) {
besetzungsList.removeAt(i);
besetzungsList.insert(i, value);
},
fromDropDown: (bool value) => fromDropDown = value,
))
],
));
}
});
setState(() {});
}
You can add that fetchEvent in your stream listener, so that it will get called after adding the user object to the array. Since it's a stream if you get a new user object, it will again call that fetchEvent and update your dropdown values.
Future<void> getUsers() async {
getCurrentUser();
usersStream = authBloc.getUsers();
usersStream.listen((allUsers) {
for (ApplicationUser user in allUsers) {
if (user.userRoleList.contains(team)) {
users.add(user.username);
}
}
await fetchEvent();
});
}
I have a url that returns a json of companies, i use the list of companies to fill a dropdown. there is another url with a parameter that returns a list of warehouses. The second method that gets the warehouses returns an empty json.
Here is the code that gets the companies. This is working alright
String? _mySelection;
final String url = "http://url:8000/companies"
Future<String> getCompanies() async {
var res = await http
.get(Uri.parse(url), headers: {
'Content-Type': 'application/json'
});
var resBody = json.decode(res.body)["data"]; // data = map["data"];
print(resBody);
setState(() {
data = resBody;
});
print(res);
return "Sucess";
}
The code that gets the warehouses is similar.
Future<String> getWarehouses(company) async {
late String warehousesUrl = "http://myWarehouseurl?company=$company";
var warehouseRes = await http
.get(Uri.parse(warehousesUrl), headers: {
'Content-Type': 'application/json'
});
var warehouseResBody = json.decode(warehouseRes.body)["data"]; // data = map["data"];
print(warehouseResBody);
setState(() {
warehouseData = warehouseResBody;
});
print(warehouseRes);
return "Sucess";
}
And my initState method
#override
void initState() {
super.initState();
this.getCompanies();
this.getWarehouses(_mySelection);
}
The dropdowns
new DropdownButton(
items: data.map((item) {
return new DropdownMenuItem(
child: new Text(item['company_name']),
value: item['company_name'].toString(),
);
}).toList(),
onChanged: (newVal) {
setState(() {
_mySelection = newVal.toString();
getWarehouses(_mySelection);
});
},
value: _mySelection,
),
_mySelection != "" ? DropdownButton(
items: warehouseData.map((item) {
return new DropdownMenuItem(
child: new Text(item['warehouse_name']),
value: item['name'].toString(),
);
}).toList(),
onChanged: (newVal) {
setState(() {
_mySelection = newVal.toString();
});
},
value: _mySelection,
) : Container(),
I am not sure why i am unable to get the values for the second dropdown, when i call the method to get the values for the warehouse in the onchange method in the companies dropdown, the data from the warehouses are printed to the console, but the app crushes.
I think you miss the async/await, lets try
new DropdownButton(
items: data.map((item) {
return new DropdownMenuItem(
child: new Text(item['company_name']),
value: item['company_name'].toString(),
);
}).toList(),
onChanged: (newVal) async{ // here need the change
setState(() {
_mySelection = newVal.toString();
await getWarehouses(_mySelection); // also here add the await
});
},
value: _mySelection,
),
I have two drop down which second is depends on first.
When i changing the first drop down value after selecting second dropdown value it throws an error as below.
So how to reset second drop down list if i changing first drop down value?
Drop down buttons are as below.
DropdownButtonFormField<Standard>(
validator: (value) {
if (value == null) {
return "Select Standard";
}
},
isExpanded: true,
hint: Text('Select Standard'),
value: selectedStandard,
items: _standards.map((Standard standard) {
return DropdownMenuItem<Standard>(
value: standard,
child: Text(standard.standardName),
);
}).toList(),
onChanged: (val) {
setState(() {
selectedStandard = val;
standardId = val?.standardId;
onMediumChange(val);
});
}),
SizedBox(height: 20),
DropdownButtonFormField<Medium>(
validator: (value) {
if (value == null) {
return "Select Medium";
}
},
isExpanded: true,
hint: Text('Select Medium'),
value: selectedMedium,
items: _mediums.map((Medium medium) {
return DropdownMenuItem<Medium>(
value: medium,
child: Text(medium.mediumName),
);
}).toList(),
onChanged: (val) {
setState(() {
selectedMedium = val;
mediumId = val?.mediumId;
});
}),
And get Values code is as below. Varibles which i used.
var _standards = <Standard>[];
var _mediums = <Medium>[];
Standard? selectedStandard;
Medium? selectedMedium;
#override
void initState() {
super.initState();
ApiManager().getStandards().then((standards) {
setState(() {
_standards = standards;
});
});
}
void onMediumChange(standard) {
setState(() {
selectedStandard = standard;
_mediums = [];
});
String mediumUrl =
"$baseUrl/medium/get_by_course_id?standard_id=${selectedStandard?.standardId}";
ApiManager().getMediums(mediumUrl).then((List<Medium> value) => {
setState(() {
_mediums = value;
})
});
}
As I understand there is a problem with selectedMedium
Try change Make it selectedMedium null inside onMediumChange
void onMediumChange(standard) {
setState(() {
selectedMedium = null;
selectedStandard = standard;
_mediums = [];
});
String mediumUrl =
"$baseUrl/medium/get_by_course_id?standard_id=${selectedStandard?.standardId}";
ApiManager().getMediums(mediumUrl).then((List<Medium> value) => {
setState(() {
_mediums = value;
})
});
}
first, check the values in _mediums because you must have a different value of selectedMedium here as according to this error !!!