i want to build Dropdown list from Future,here is my function for simple list view which is working,,but how to populate drop down list from it, i am really confuse about this list map etc in flutter coming from php background,
child: FutureBuilder(
future:userApi.getUsers(),
builder: (BuildContext context, AsyncSnapshot snapshot){
if(snapshot.data == null){
return Container(
child: Center(
child: Text("Loading...")
)
);
} else {
return Container(
child: DropdownButton(
items: snapshot.data.map((item) {
return DropdownMenuItem(child: Text(item.title));
}).toList(),
onChanged: (value){},
)
);
}
},
),
class UserApi{
Future<List<User>>getUsers() async {
var data = await http.get("https://jsonplaceholder.typicode.com/albums/");
var jsonData = json.decode(data.body);
List<User> users = [];
for(var u in jsonData){
User user = User(u["id"], u["title"]);
users.add(user);
}
return users;
}
class User {
final int id;
final String title;
User(this.id,this.title);
}
Ok I just read the comment left above if your problem is getting your data then this might not help you but if snapshot has data this will work
//initialize this outside your build method
String dropDownValue;
FutureBuilder(
future:userApi.getUsers(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
return snapshot.hasData
? Container(
child: DropdownButton<String>(
hint: Text(dropDownValue ?? 'Make a selection'),
items: snapshot.data.map<DropdownMenuItem<String>>((item) {
return DropdownMenuItem<String>(
value: item.title,
child: Text(item.title),
);
}).toList(),
onChanged: (value) {
setState(() {
dropDownValue = value;
print(value);
});
},
),
)
: Container(
child: Center(
child: Text('Loading...'),
),
);
},
),
you can call the map function on any list converting the elements of the list.
return DropdownButton(
items: snapshot.data.map((item) {
return DropdownMenuItem(child: Text(item.title));
}).toList(),
onChanged: (value){},
);
if you can see here we're converting the list snapshot.data to another list of DropdownMenuItem type by calling map on snapshot.data the map function takes another function that's being called on every element of snapshot.data , map returns an Iterable of type DropdownMenuItem (the returned type of the function being called on every element) and we convert the Iterable to a list by calling toList() on it
I wish that is explanatory enough, the map function is very useful.
Related
I'm having an issue with duplicate DropdownMenuItem while getting the menu item's value from Firestore.
I want to get all the 'from' attributes values from 'routes' collection excluding the duplicates. And i want to show them inside my DropDownButton.
My Sample Code:
late final Stream<QuerySnapshot> routes = Database().getRoutes();
StreamBuilder<QuerySnapshot>(
stream: routes,
builder: (
BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot,
) {
final data = snapshot.requireData;
fromValue.value = data.docs[0]['from'];
destinationValue.value = data.docs[0]['to'];
return Column(
children: [
Obx(() {
return DropdownButton(
// Initial Value
value: fromValue.value,
// Down Arrow Icon
icon: const Icon(Icons.keyboard_arrow_down),
alignment: AlignmentDirectional.center,
underline: Container(
height: 1,
color: Colors.deepPurple.shade100,
),
// list of items
items: data.docs.map(
(DocumentSnapshot doc) {
return DropdownMenuItem<
String>(
value: doc['from']
.toString(),
child:
Text(doc['from']));
}).toList(),
// After selecting the desired option,it will
// change button value to selected value
onChanged: (newValue) {
fromValue.value = newValue.toString();
},
);
}),
],
);
}),
Method Used To Fetch Firestore Data:
getRoutes() {
final Stream<QuerySnapshot> routes = db
.collectionGroup("routes")
.snapshots();
return routes;
}
hello guys as a beginner on flutter i'm having an issue with the dropdownbutton widget as shown on the joined GIF
on the backend everything seems to work normally every row n the list has it Answer properly but on the screen the values changes for the whole screen not row by row
that's the source code for the ChangeNotifier() :
class ChoiceHandler extends ChangeNotifier {
final List<String> _dropdownElements = ['Not Done', 'Partially Done', 'Done'];
List<String> get dropdownElement => _dropdownElements;
late String _selectedItemValue;
String get selected => _selectedItemValue;
selectedValues(String s) {
_selectedItemValue = s;
notifyListeners();
}
}
and under listView here is the code for the dropdownButton :
Expanded(
child: ListView.builder(
itemCount: propositions.length,
itemExtent: 50.0,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(propositions[index]),
trailing: Consumer<ChoiceHandler>(
builder: (_, provider, __) {
return DropdownButton<String>(
value: dropdownValue,
onChanged: (newValue) {
provider.selectedValues(newValue as String);
dropdownValue = newValue;
print((propositions[index]) + " " + newValue); // here i can the results when i'm changing values
},
items: provider.dropdownElement
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
},
) //_dropdown(index),
);
thanks in advance
i've found the issue i've misplaced the declaration of a veriable ,th variable
"dropdownValue" was declared above as a global variable , and then i've changed it place to where it's shown on the source code :
child: ListView.builder(
itemCount: propositions.length,
itemExtent: 50.0,
itemBuilder: (BuildContext context, int index) {
String dropdownValue = "Not Done"; // <==== i declared it here
return ListTile(
title: Text(propositions[index]),
trailing: Consumer<ChoiceHandler>(
builder: (_, provider, __) {
return DropdownButton<String>(
value: dropdownValue,
onChanged: (newValue) {
provider.selectedValues(newValue as String);
dropdownValue = newValue;
print((propositions[index]) + " " + newValue);
},
items: provider.dropdownElement
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
},
) //_dropdown(index),
);
I am getting a data from local database using floor in flutter.
And I want to display the list of doctors from the db I am using DropDownButton to do this
This is my code
DropdownButton(
icon: const Icon(
Icons.arrow_drop_down,
),
hint: const Text('Select a doctor'),
items: FutureBuilder<List<Doctor>>(
future: findAllDoctor(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return snapshot.data
.map((doctor) => DropdownMenuItem(
child: Text(doctor.name),
value: doctor,
))
.toList();
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return CircularProgressIndicator();
}
), ,
onChanged: (val) {
print(val);
},
),
And this is how I get the data
Future<List<Doctor>> findAllDoctor() async {
return await database.doctorDao.findAllDoctor();
}
I am getting this error
The argument type 'FutureBuilder<List<Doctor>>' can't be assigned to the parameter type 'List<DropdownMenuItem<Object>>?'.
What I need here is to display the doctors as list in a form to choose from.
Your FutureBuilder was placed in wrong place, check my edited code:
FutureBuilder<List<Doctor>>(
builder: (context, snapshot) {
if (snapshot.hasData) {
return DropdownButton<String>(
icon: const Icon(
Icons.arrow_drop_down,
),
hint: const Text('Select a doctor'),
items: snapshot.data
?.map((doctor) => DropdownMenuItem(
child: Text(doctor.name),
value: doctor.name,
))
.toList(),
onChanged: (val) {
print(val);
},
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return const CircularProgressIndicator();
},
);
I create apps that user can load csv file and i want csv data put into map so that i can make delete function or anything else.... Can somebody help me because i been searching for this it show how to convert csv using loadasset bundle i want to do it with pick file from phone storage
example: convert data from a csv to a dynamic List (Flutter)
I/flutter ( 4028): [[No, Name, Code], [1, Ali, A123], [2, Abu, B456], [3, Amir, C789], [4, Safe, D098], [5, Alif, E765 ]]
here my code
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("CSV DATA"),
backgroundColor: Colors.redAccent[400],
),
body: Container(
child: SingleChildScrollView(
child: Column(children: <Widget>[
FutureBuilder(
future: loadingCsvData(path),
builder: (context, AsyncSnapshot<List<dynamic>> snapshot) {
print(snapshot.data.toString());
return snapshot.hasData
? ListView(
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: snapshot.data.map((data) {
return Visibility(
visible: visibilityController,
child: //Your card
Card(
child: GestureDetector(
onTap: () {
withInputField(context);
controller.text = data[1];
_controller.text = data[2];
setState(() {});
},
child: ListTile(
title: Text(
data[1].toString(),
style: TextStyle(
fontWeight: FontWeight.bold),
),
subtitle: Text(data[2].toString()),
isThreeLine: true,
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () {},
),
),
),
));
}).toList(),
)
: Center(
child: CircularProgressIndicator(),
);
},
),
]),
)),
This my function for file picker
Future<List<List<dynamic>>> loadingCsvData(String path) async {
final csvFile = new File(path).openRead();
return await csvFile
.transform(utf8.decoder)
.transform(
CsvToListConverter(),
)
.toList();
}
EDIT
my fetch data
FutureBuilder(
future: loadingCsvData(path),
builder: (context,
AsyncSnapshot<Map<int, Map<String, dynamic>>> snapshot) {
print(snapshot.data.toString());
return snapshot.hasData
? ListView(
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: [
Card(
child: ListTile(
title: Text(userList.toString()),
),
)
],
)
: Center(
child: CircularProgressIndicator(),
);
},
),
is it right to do like this
I would create a model for the object you want to read.
Whithin the model I would prepare some functions to convert a single of your Row in a Map<String, dynamic> and to convert a List of Rows in a Map<int, Map<String, dynamic>>.
Here's an example:
//I suppose your single row element to be an User
class User {
User({
No,
Name,
Code,
}) {
this.No = No;
this.Name = Name;
this.Code = Code;
}
//Parameters
int? No;
String? Name;
String? Code;
// A map with an String key and dynamic value
static Map<String, dynamic> userToMap(List<dynamic> row) {
return {
if (row[0] != null) 'No': row[0] as int,
if (row[1] != null) 'Name': row[1] as String,
if (row[2] != null) 'Code': row[2] as String
};
}
// A map with an int key and Map<String, dynamic> value
static Map<int, Map<String, dynamic>> userListToMap(
List<List<dynamic>> userList) {
userList.removeAt(0); //If you want to remove the first row containing the headers
return userList.map((user) => userToMap(user)).toList().asMap();
}
}
Then you could take the List<List<dynamic>> returned from your method loadingCsvData and call userListToMap.
UPDATE:
After writing my answer I noticed that you don't actually need the class I built, you could take the functions userToMap and userListToMap alone and it should work.
EDIT:
You could change your loadingCsvData to look like this:
Future<Map<int, Map<String, dynamic>>> loadingCsvData(String path) async {
final csvFile = new File(path).openRead();
return userListToMap(await csvFile
.transform(utf8.decoder)
.transform(
CsvToListConverter(),
).toList());
}
I am trying to make a dropdown select input in flutter! I want to get the data from a future list ref.
I am not sure how to go about it, as this gives me error :
Here is the code:
dropdownButtonHideUnderline(FormFieldState<String> state) {
return FutureBuilder(
future: Global.payCountriesRef.getData(),
builder: (BuildContext context, AsyncSnapshot snap) {
if (snap.hasData) {
List<PayCountries> countries = snap.data;
return new DropdownButtonHideUnderline(
child: new DropdownButton<String>(
value: _sendForm.country,
isDense: true,
onChanged: (String newValue) {
setState(() {
_sendForm.country = newValue;
//_updateDropdownValue(newValue, model);
state.didChange(newValue);
});
},
items: List<String>.from(countries)
.map((String value) {
return new DropdownMenuItem<String>(
value: value,
child: new Text(value),
);
}).toList()
),
);
}
}
);
}
The code Below shows an example to populate a dropdown from a future list
new DropdownButtonHideUnderline(
child: new FutureBuilder<List<BranchItems>>(
future: new BranchService().fetchBranchItems(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return new Container();
} else if (snapshot.hasData) {
list.clear();
//listItemNames.clear();
dropDownItemsMap = new Map();
snapshot.data.forEach((branchItem) {
//listItemNames.add(branchItem.itemName);
int index = snapshot.data.indexOf(branchItem);
dropDownItemsMap[index] = branchItem;
list.add(new DropdownMenuItem(
child: new DropDownItem(
image: Image.network(branchItem.itemPicture),
text: branchItem.itemName),
value: index));
});
return DropdownButton(
items: list,
onChanged: (int selected) {
_selectedItem = list[selected].value;
setState(() {
selectedItemName =
dropDownItemsMap[_selectedItem].itemName;
});
},
hint: new Text(
selectedItemName,
style: new TextStyle(color: Colors.blue),
),
);
} else {
return CircularProgressIndicator();
}
},
),
),