I'm using an API which returns the value like this.
[
{
"store": "AMAZON"
},
{
"store": "FLIPKART"
},
{
"store": "WALMART"
},
{
"store": "ALIBABA"
},
]
I need this to be in a drop down.
I need a drop down button with this API data in it. Some one help please. I have tried many ways but nothing worked.
nigale try code:
List<String> markets = []; // Or var markets = [];
String _mySelection;
#override
void initState() {
buidDropDownItems();
super.initState();
}
//
void buidDropDownItems() async {
markets = await retrievedata.getMarket();
// Refresh the UI if the State object has been created
if(mounted){
setState(() {});
}
}
child: DropdownButton(
items: markets.map<DropdownMenuItem<String>>((String val){
return DropdownMenuItem<String>(value: val, child: Text(val));
}).toList(), // Get items from the available data in markets variable
onChanged: (sto) {
setState(() {
_mySelection = sto;
});
},
value: _mySelection,
hint: Text('Please select the store: '),
),
The function retrievedata.getMarket(); is returning Future<dynamic> which dynamic is your markets list.
let's say that this array is retrieved in a variable called data
List<String>list=[];
for(var itemData in data){
list.add(itemData['store']);
}
And wala, Now list conation array of String ready to be used
Related
String? _selectedCity;
List cities = ['Select City'];
#override
void initState() {
super.initState();
_secureText = true;
_getCities();
}
Future _getCities() async {
var url = "baseurl/api/v1/cities";
try {
var response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
var data = json.decode(response.body);
setState(() {
cities = data;
});
}
print(cities);
} catch (e) {
// ignore: avoid_print
print("Error: $e");
}
}
DropdownButton(
hint
: const Text("Select City"), value
: _selectedCity, items
: cities
.map((category) {
return DropdownMenuItem(value
: category['name'], child
: Text(category['name']), );
})
.toList(),
onChanged
: (value) { setState(() { _selectedCity = value as String ? ; }); })
there is problem in my Dropdown Button
Value from dropdown were seen before but after update of 2023/1/25, i am facing error "type 'String' is not a subtype of type 'int' of 'index'"
Replace this code in your own code. must be correct.
DropdownButton(
hint: const Text("Select City"),
value: _selectedCity,
items: cities
.map((category) {
return DropdownMenuItem(
value: category['name'],
child: Text(category['name'])
);
})
.toList(),
onChanged: (value) {
setState(() {
_selectedCity = value;
});
})
I tried to retrieve data from the API to display in the dropdown but an error occurred, I've tried according to what I was looking for on google and also the forum but the problem still appears.
is there something wrong in writing in my code,
Thank you
this is the function that is executed when calling the api and the
response is 200.
class UtilFunction {
String? _valMenu;
var _dataMenu = [];
Future getSemester() async {
String url = Constant.baseURL;
String token = await UtilSharedPreferences.getToken();
final respose = await http.get(
Uri.parse(
'$url/auth/semester/get_smt',
),
headers: {
'Authorization': 'Bearer $token',
},
);
await http
.get(
Uri.parse(
'$url/auth/semester/get_smt',
),
)
.then((value) => (() {
// respose = value; //untuk melakukan request ke webservice
var listData =
jsonDecode(respose.body); //lalu kita decode hasil datanya
_dataMenu = listData['data'];
_valMenu = _dataMenu[0]['data'];
}));
print(respose.statusCode);
print(respose.body);
return _dataMenu;
}
}
and I take the above function here.
Container(
child: FutureBuilder(
future: UtilFunction().getSemester(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
DropdownButtonFormField(
value: _valMenu,
onChanged: (value) {},
items: snapshot.data
.map<DropdownMenuItem>(
(project) => DropdownMenuItem(
value: project['smt'],
child: Text(project['smt']),
))
.toList,
), ...
this response json
{
"status": "success",
"code": "200",
"data": [
{
"id": "254dd6e9-791e-4a2b-959e-6ec5929f3104",
"id_ta": "2b4d2dd1-ef8e-461b-b7c3-48409a13969e",
"ta": "2022-2023",
"smt": "GANJIL",
"semester": "2022-2023 GANJIL",
"periode_awal": "Senin, 01 Agustus 2022",
"periode_akhir": "Minggu, 22 Januari 2023",
"p_awal": "2022-08-01",
"p_akhir": "2023-01-22",
"period_smt": "Senin, 01 Agustus 2022 - Minggu, 22 Januari 2023",
"created_at": "2022-08-10 05:02:18",
"updated_at": "2022-09-06 03:57:00",
"created_by": "Superadmin",
"updated_by": "Dasep",
"sts_hapus": 1
}
]
}
there are some problems with you get data and how you print it. I have used public api you can change the url.
class UtilFunction {
String? _valMenu;
List<String> _dataMenu = [];
Future getSemester() async {
await http.get(Uri.parse("http://universities.hipolabs.com/search?country=United+States")).then((value) {
// respose = value; //untuk melakukan request ke webservice
var listData = jsonDecode(value.body); //lalu kita decode hasil datanya
for (var i = 0; i < 10; i++) {
_dataMenu.add(listData[i]["domains"][0]);
}
_valMenu = _dataMenu[0];
});
return _dataMenu;
}
}
Also I have made some changes in FutureBuilder. Note that you will also need to change return type of your api call to give first element of the dropdown value.
FutureBuilder(
future: UtilFunction().getSemester(),
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
val = snapshot.data[0];
return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
DropdownButton<String>(
value: val,
onChanged: (value) {
val = value!;
},
items: snapshot.data
.map<DropdownMenuItem<String>>((String project) => DropdownMenuItem<String>(
value: project,
child: Text(project),
))
.toList(),
),
]);
} else {
return Text("dsds");
}
})
Change List<DropdownMenuItem> to List<DropdownMenuItem<String>>
snapshot.data
.map<DropdownMenuItem<String>>(
(project) => DropdownMenuItem<String>(
value: project['smt'],
child: Text(project['smt']),
))
.toList()
Also In the decoding try this
var listData = jsonDecode(respose.body); as Map<String, dynamic>
if(listData.containsKey('data')){
_dataMenu = listData['data'];
_valMenu = _dataMenu[0]['data'];
} else {
// HANDLE NO DATA SCENARIO
}
}
So I have the following code to showModalBottomSheet, and display filters/checkboxes on the page. If I exit the modal and show the showModalBottomSheet again, then I don't see the checkbox values got preserved.
It seems the 2nd time I show the modal, the build() from _CheckboxStatefulWidgetState was called again, and then default the checkValue to null.
Here is filter.dart
import 'package:flutter/material.dart';
import '../helper/checkbox.dart';
mixin ListFilter<T extends StatefulWidget> on State<T> {
dynamic filters = [
{
"name": "name1",
"choices": [
{'label': 'label1', 'value': 'value1', 'check': false},
{'label': 'label2', 'value': 'value2', 'check': false},
],
},
{
"name": "nameA",
"choices": [
{'label': 'labelA', 'value': 'valueA', 'check': false},
{'label': 'labelB', 'value': 'valueB', 'check': false},
],
},
];
dynamic filterWidgets;
void showFilterModal(context, dynamic filters) {
showModalBottomSheet<void>(
context: context,
//isScrollControlled: true,
builder: (BuildContext context) {
if (filterWidgets == null) {
print("----> filterWidgets is null");
filterWidgets = _getFilterWidgets(filters);
}
return Container(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: filterWidgets),
),
);
},
);
}
List<Widget> _getFilterWidgets(dynamic filters) {
List<Widget> children = [];
for (var i = 0; i < filters.length; i++) {
dynamic filter = filters[i];
dynamic choices = filter['choices'];
for (var j = 0; j < choices.length; j++) {
dynamic choice = choices[i];
children.add(CheckboxStatefulWidget(
label: choice['label']));
}
Widget divider = Divider();
children.add(divider);
}
return children;
}
}
Here is checkbox.dart
import 'package:flutter/material.dart';
class CheckboxStatefulWidget extends StatefulWidget {
final String label;
CheckboxStatefulWidget({Key key, this.label}) : super(key: key);
#override
_CheckboxStatefulWidgetState createState() =>
_CheckboxStatefulWidgetState();
}
class _CheckboxStatefulWidgetState extends State<CheckboxStatefulWidget> {
bool checkValue;
#override
Widget build(BuildContext context) {
print("checkValue: $checkValue");
print(checkValue == true ?? false);
return CheckboxListTile(
title: Text(this.widget.label),
value: checkValue == true ?? false,
onChanged: (bool newValue) {
setState(() {
checkValue = newValue;
});
});
}
}
I think you can try with this solution:
Define a variable to store currently filter options.
When user submit options filter -> let pop that filter.
note: Modal will create again when you show on 2nd. So you need pop that option to parent widget to store.
FilterModel currentFilterOptions;
Future<FilterModel> showFilterModal(context, FilterModel filters) {
//Show modal
}
...
showFilterModal(context, currentFilterOptions).then((value) {
currentFilterOptions = value;
//DO STH
});
This is the error I have got:
Here is my DropdownButton code:
DropdownButton countryPicker() {
return DropdownButton<String>(
onChanged: (value) {
setState(() {
country = value;
});
},
value: country,
hint: Text(country),
items: countries(),
);
}
List<DropdownMenuItem<String>> countries() {
List<DropdownMenuItem<String>> list = [];
countryDetails.forEach((c) {
list.add(DropdownMenuItem<String>(
child: Text(c.countryName),
value: c.countryName,
));
});
return list;
}
All of my data list is in countryDetails variable.
And the list is like this:
[
{
"country_name": "Andorra",
"alpha2_code": "AD",
"states": [
{"state_name": "Andorra la Vella"},
{"state_name": "Canillo"},
]
},
..............
..............
]
So, whats the problem here?
In the error it says you have two or more DropdownMenuItem with the same value, which is not allowed.
When I take a look at your code, it seems like you are passing c.countryName as the value, but could you double check and make sure that all of your country_name are unique?
when use response from API then show error
The getter 'length' was called on null.
Receiver: null
Tried calling: length
here is my API code
var url =
"https://domain.php";
var res;
var splashs;
void initState() {
super.initState();
fetchData();
}
fetchData() async {
res = await http.get(url);
splashs = jsonDecode(res.body);
setState(() {});
}
while use List then code working properly
List<Map<String, String>> splashs = [
{
"header": "Flatros",
"text": "Welcome to Flatros, Let’s shop!",
"image_name": "assets/images/splash_1.png"
},
{
"header": "Shopping",
"text":
"We help people conect with store \naround United State of America",
"image_name": "assets/images/splash_2.png"
},
{
"header": "Multi Category",
"text": "FInal Screen",
"image_name": "assets/images/splash_3.png"
},
];
May be you need to convert your data into List or Array
List splashs = new List();
fetchData() async {
res = await http.get(url);
final data = jsonDecode(res.body);
for (var i in data) {
splashs.add(i); // Create a list and add data one by one
}
setState(() {});
}