How to populate a Flutter dropdown box - flutter

How do I populate a Flutter Dropdown box?. I have the following key value pair data.
I want to show the user the value (name) and on click get the ID value
[
{'Id': '1', 'Name': 'item 1'}
{ 'Id': '2', 'Name': 'item 2' }
{ 'Id': '3', 'Name': 'item 3' }
]

Use the map function against the list to generate what you need.
final myMapList = [
{'Id': '1', 'Name': 'item 1'},
{ 'Id': '2', 'Name': 'item 2' },
{ 'Id': '3', 'Name': 'item 3' },
];
String _newValue = myMapList[0]['Id'];
...
DropdownButton<String>(
value: _newValue,
onChanged: (String newValue) {
setState(() {
_newValue = newValue;
});
},
items: myMapList.map(
(Map item) {
return DropdownMenuItem<String>(
value: item['Id'],
child: Text(
item['Name'],
);
}).toList(),),

Related

Flutter/Dart: How to get value in a list of maps?

It's propably very simple question, but i can't find a solution. How to get a 'Answer 1', 'Answer 2',etc. from this map and put them in to Text widget in loop? I'm trying to make questionnaire and i need to get values of 'text'.
I simplified the code as much as possible:
final questions = const [
{
'questionText': 'This is the first question?',
'answers': [
{'text': 'Answer 1', 'answer': 1},
{'text': 'Answer 2', 'answer': 2},
{'text': 'Answer 3', 'answer': 3},
{'text': 'Answer 4', 'answer': 4},
],
},
{
'questionText': 'This is the second question?',
'answers': [
{'text': 'Answer 1', 'answer': 1},
{'text': 'Answer 2', 'answer': 2},
{'text': 'Answer 3', 'answer': 3},
{'text': 'Answer 4', 'answer': 4}
],
},
];
int numberOfAnswers = 4;
int questionIndex = 0;
Column(
children: [
for (var i = 0; i < numberOfAnswers; i++)
Text('Answer (1,2,3,4)'),
],
),
Tried: questions[questionIndex]['answers']['text'], etc, but it doesn't work.
You can get specific question with questions[index]["questionText"];
and its answer questions[index]["answers"] as List?;
Here is the example
class Fasd4 extends StatelessWidget {
const Fasd4({super.key});
final questions = const [
{
'questionText': 'This is the first question?',
'answers': [
{'text': 'Answer 1', 'answer': 1},
{'text': 'Answer 2', 'answer': 2},
{'text': 'Answer 3', 'answer': 3},
{'text': 'Answer 4', 'answer': 4},
],
},
{
'questionText': 'This is the second question?',
'answers': [
{'text': 'Answer 1', 'answer': 1},
{'text': 'Answer 2', 'answer': 2},
{'text': 'Answer 3', 'answer': 3},
{'text': 'Answer 4', 'answer': 4}
],
},
];
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: questions.length,
itemBuilder: (context, index) {
final question = questions[index]["questionText"];
final answers = questions[index]["answers"] as List?;
return Column(
children: [
Container(
height: kToolbarHeight,
color: Colors.deepPurple,
alignment: Alignment.center,
child: Text("$question")),
for (var i = 0; i < (answers?.length ?? 0); i++)
Text(
"text: ${answers?[i]['text']} : answer ${answers?[i]['answer']} "),
],
);
},
));
}
}
It would be better if you create model class for it.
You can access your answers and list them the following way:
class TestWidget extends StatelessWidget {
TestWidget({Key? key}) : super(key: key);
final List<Map<String, dynamic>> questions = [
{
'questionText': 'This is the first question?',
'answers': [
{'text': 'Answer 1', 'answer': 1},
{'text': 'Answer 2', 'answer': 2},
{'text': 'Answer 3', 'answer': 3},
{'text': 'Answer 4', 'answer': 4},
],
},
{
'questionText': 'This is the second question?',
'answers': [
{'text': 'Answer 1', 'answer': 1},
{'text': 'Answer 2', 'answer': 2},
{'text': 'Answer 3', 'answer': 3},
{'text': 'Answer 4', 'answer': 4}
],
},
];
final int numberOfAnswers = 4;
final int questionIndex = 0;
#override
Widget build(BuildContext context) {
return Column(
children: [
for (int i = 0; i < numberOfAnswers; i++) ...[
Text(questions[questionIndex]['answers'][i]['text']),
],
],
);
}
}
Loop through both questions and answers:
for (var question in questions) {
print(question['questionText']);
final answers = question['answers'] as List;
for (var answer in answers) {
print(answer['text']);
}
}
Output:
This is the first question?
Answer 1
Answer 2
Answer 3
Answer 4
This is the second question?
Answer 1
Answer 2
Answer 3
Answer 4

Flutter code issue where i can't put in a background image behind my dropdownbutton

I have spent a lot of hours trying to figure out why my background image wont get behind my dropdownbutton, but always stays like... Inside my button if that makes any sence ?
I am brand new to flutter, so help would be appreciated.
The list works btw... I just have problems with putting a background image behind the dropdownbutton.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Rejsen Til Gardasøen',
theme: ThemeData(
primarySwatch: Colors.lightBlue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: RejsenTilGarda(),
debugShowCheckedModeBanner: false,
);
}
}
class RejsenTilGarda extends StatefulWidget {
#override
_RejsenTilGardaState createState() => _RejsenTilGardaState();
}
class _RejsenTilGardaState extends State<RejsenTilGarda> {
var _selected;
final List<Map> _myArmsJson = [
{'id': '1', 'image': 'images/bardolino.png', 'name': 'Bardolino'},
{'id': '2', 'image': 'images/brenzone.png', 'name': 'Brenzone'},
{'id': '3', 'image': 'images/campione.png', 'name': 'Campione'},
{'id': '4', 'image': 'images/castelnuovo.png', 'name': 'Castelnuovo'},
{'id': '5', 'image': 'images/desenzano.png', 'name': 'Desenzano'},
{'id': '6', 'image': 'images/garda.png', 'name': 'Garda'},
{'id': '7', 'image': 'images/gardone.png', 'name': 'Gardone'},
{'id': '8', 'image': 'images/gargnano.png', 'name': 'Gargnano'},
{'id': '9', 'image': 'images/lazise.png', 'name': 'Lasize'},
{'id': '10', 'image': 'images/limone.png', 'name': 'Limone Sul Garda'},
{'id': '11', 'image': 'images/lonato.png', 'name': 'Lonato'},
{'id': '12', 'image': 'images/malcesine.png', 'name': 'Malcesine'},
{'id': '13', 'image': 'images/manerba.png', 'name': 'Manerba'},
{'id': '14', 'image': 'images/moniga.png', 'name': 'Moniga'},
{'id': '15', 'image': 'images/nagoTorbole.png', 'name': 'Nago-Torbole'},
{'id': '16', 'image': 'images/padenghe.png', 'name': 'Padenghe'},
{'id': '17', 'image': 'images/peschiera.png', 'name': 'Peschiera'},
{'id': '18', 'image': 'images/puegnago.png', 'name': 'Puegnago'},
{'id': '19', 'image': 'images/riva.png', 'name': 'Riva Del Garda'},
{'id': '20', 'image': 'images/salo.png', 'name': 'Salò'},
{
'id': '21',
'image': 'images/sanFelice.png',
'name': 'San Felice Del Benaco'
},
{'id': '22', 'image': 'images/sirmione.png', 'name': 'Sirmione'},
{'id': '23', 'image': 'images/soiano.png', 'name': 'Soiano'},
{'id': '24', 'image': 'images/tignale.png', 'name': 'Tignale'},
{'id': '25', 'image': 'images/torri.png', 'name': 'Torri Del Benaco'},
{
'id': '26',
'image': 'images/toscolanoMaderno.png',
'name': 'Toscolano-Maderno'
},
{'id': '27', 'image': 'images/tremosine.png', 'name': 'Tremosine'},
];
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
centerTitle: true,
backgroundColor: Colors.white,
title: Text('Rejsen Til Gardasøen')),
body: Center(
child: Container(
width: 300.0,
decoration: BoxDecoration(
border: Border.all(width: 1, color: Colors.white),
borderRadius: BorderRadius.circular(10)),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: true,
child: DropdownButton(
hint: Text('Vælg en by'),
value: _selected,
onChanged: (newValue) {
setState(() {
_selected = newValue.toString();
});
},
items: _myArmsJson.map((city) {
return DropdownMenuItem(
value: city['id'].toString(),
child: Row(
children: [
Image.asset(city['image'], width: 25),
Container(
margin: EdgeInsets.only(left: 10),
child: Text(city['name']),
),
],
),
);
}).toList(),
),
),
),
),
],
),
),
),
),
);
}
}

Flutter pass data from DropdownButton to api

I just wanted to map to api and make the following DropdownButton in flutter that posts data to API when an item is selected
DropdownButton(
value: 'Item 1',
icon: const Icon(Icons.keyboard_arrow_down),
items: [
'Item 1',
'Item 2',
'Item 3',
'Item 4',
'Item 5',
].map((String items) {
return DropdownMenuItem(
value: items,
child: Text(items),
);
}).toList(),
onChanged: print),
how can I map to api endpoint and post the selected item to api?
As a post request with an integer instead of string:
Future<void> onChangedCallback(int? item) async {
if(item != null){
currentValue = item;
final url = "your_url_here";
final body = {
"key_you_want_to_map": item
};
final response = await http.post(Uri.parse(url), body: body);
print(response.body);
}
}
...
var currentValue = 1;
DropdownButton(
value: currentValue,
icon: const Icon(Icons.keyboard_arrow_down),
items: <int>[
1,
2,
3,
4,
5,
].map((int i) {
return DropdownMenuItem(
value: i,
child: Text('Item $i'),
);
}).toList(),
onChanged: onChangedCallback,
), // Equivalent of onChanged: (v) async => onChangedCallback(v),

Editable DataTable only works when being the only Widget in the Scaffold body

I have created a custom DataTable, which is editable in a StatefulWidget. The DataTable only loads and works, when there are no other widgets in the Scaffold body property. For example, when I try to add the DataTable in a Column it won't load.
Any help is appreciated, here's the source code of the main.dart, in case that helps.
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Abiturwahlbogen'),
centerTitle: true,
),
body:
Column(
children: const <Widget> [
KursListe(),
],
),
),
),
);
}
class KursListe extends StatefulWidget {
const KursListe({Key? key}) : super(key: key);
#override
State<KursListe> createState() => KursListeState();
}
class KursListeState extends State<KursListe> {
final List<Map> _books = [
{'Kategorie': 'LNG', 'title': 'Deutsch', 'id': 'D', 'LNGFolge': '', 'LNGDauer': '', 'EF.1': '', 'EF.2': '', 'Q1.1': '', 'Q1.2': '', 'Q2.1': '', 'Q2.2': '', 'ABI': '',},
{'Kategorie': 'LNG', 'title': 'Englisch', 'id': 'E', 'LNGFolge': '1', 'LNGDauer': '5', 'EF.1': '', 'EF.2': '', 'Q1.1': '', 'Q1.2': '', 'Q2.1': '', 'Q2.2': '', 'ABI': '',},
{'Kategorie': 'NW', 'title': 'Mathematik', 'id': 'M', 'LNGFolge': '', 'LNGDauer': '', 'EF.1': '', 'EF.2': '', 'Q1.1': '', 'Q1.2': '', 'Q2.1': '', 'Q2.2': '', 'ABI': '',},
{'Kategorie': 'NW', 'title': 'Physik', 'id': 'PH', 'LNGFolge': '', 'LNGDauer': '', 'EF.1': '', 'EF.2': '', 'Q1.1': '', 'Q1.2': '', 'Q2.1': '', 'Q2.2': '', 'ABI': '',},
{'Kategorie': 'GW', 'title': 'Erdkunde', 'id': 'EK', 'LNGFolge': '', 'LNGDauer': '', 'EF.1': '', 'EF.2': '', 'Q1.1': '', 'Q1.2': '', 'Q2.1': '', 'Q2.2': '', 'ABI': '',},
{'Kategorie': 'GW', 'title': 'Geschichte', 'id': 'GE', 'LNGFolge': '', 'LNGDauer': '', 'EF.1': '', 'EF.2': '', 'Q1.1': '', 'Q1.2': '', 'Q2.1': '', 'Q2.2': '', 'ABI': '',},
];
#override
Widget build(BuildContext context) {
return SizedBox(
child: ListView(
children: [_createDataTable()],
));
}
DataTable _createDataTable() {
return DataTable( columnSpacing: 30.0, columns: _createColumns(), rows: _createRows());
}
List<DataColumn> _createColumns() {
return [
const DataColumn(label: Text('Ktg')),
const DataColumn(label: Text('Fach')),
const DataColumn(label: Text('Kürzel')),
const DataColumn(label: Text('Spr-Folge')),
const DataColumn(label: Text('Ab Jg.')),
const DataColumn(label: Text('EF.1')),
const DataColumn(label: Text('EF.2')),
const DataColumn(label: Text('Q1.1')),
const DataColumn(label: Text('Q1.2')),
const DataColumn(label: Text('Q2.1')),
const DataColumn(label: Text('Q2.2')),
const DataColumn(label: Text('Abitur'))
];
}
List<DataRow> _createRows() {
return _books
.map((book) => DataRow(cells: [
DataCell(Text(book['Kategorie'])),
DataCell(Text(book['title'])),
DataCell(Text(book['id'])),
DataCell(Text(book['LNGFolge'])),
DataCell(Text(book['LNGDauer'])),
DataCell(TextButton(onPressed: () {
setState(() {
book['EF.1']= clickConditions(book['EF.1']);
});
},
child: Text(book['EF.1']),
),),
DataCell(TextButton(onPressed: () {
setState(() {
book['EF.2']= clickConditions(book['EF.2']);
});
},
child: Text(book['EF.2']),
),),
DataCell(TextButton(onPressed: () {
setState(() {
book['Q1.1']= clickConditions(book['Q1.1']);
});
},
child: Text(book['Q1.1']),
),),
DataCell(TextButton(onPressed: () {
setState(() {
book['Q1.2']= clickConditions(book['Q1.2']);
});
},
child: Text(book['Q1.2']),
),),
DataCell(TextButton(onPressed: () {
setState(() {
book['Q2.1']= clickConditions(book['Q2.1']);
});
},
child: Text(book['Q2.1']),
),),
DataCell(TextButton(onPressed: () {
setState(() {
book['Q2.2']= clickConditions(book['Q2.2']);
});
},
child: Text(book['Q2.2']),
),),
DataCell(TextButton(onPressed: () {
setState(() {
book['ABI']= clickConditions(book['ABI']);
});
},
child: Text(book['ABI']),
),),
]))
.toList();
}
clickConditions (String s1) {
if (s1=='') {
s1 = 'M';
}
else if (s1=='M') {
s1 = 'S';
}
else {
s1 = '';
}
return s1;
}
}
I have tried to use different Widgets like Containers, but the problem seems to be that the DataTable is not compatible.

ion-picker can't get role of button clicked

I can’t seem to get the button role from ion-picker.
I need to know if it was ‘done’ or ‘cancel’.
Any ideas why this is?
I am just padding this out as stackoverflow is asking me to write some more details as my post is mostly code.
They data is just coming back as follows:
{data: undefined, role: undefined}
let opts: PickerOptions = {
cssClass: 'time-picker',
buttons: [
{
text: 'Cancel',
role: 'cancel'
},
{
text: 'Done',
role: 'done'
}
],
columns: [
{
name: 'hour',
options: [
{ text: '01', value: '01' },
{ text: '02', value: '02' },
{ text: '03', value: '03' },
{ text: '04', value: '04' },
{ text: '05', value: '05' },
{ text: '06', value: '06' },
{ text: '07', value: '07' },
{ text: '08', value: '08' },
{ text: '09', value: '09' },
{ text: '10', value: '10' },
{ text: '11', value: '11' },
{ text: '12', value: '12' },
{ text: '13', value: '13' },
{ text: '14', value: '14' },
{ text: '15', value: '15' },
{ text: '16', value: '16' },
{ text: '17', value: '17' },
{ text: '18', value: '18' },
{ text: '19', value: '19' },
{ text: '20', value: '20' },
{ text: '21', value: '21' },
{ text: '22', value: '22' },
{ text: '23', value: '23' },
{ text: '24', value: '24' }
]
},
{
name: 'minute',
options: [
{ text: '00', value: '00' },
{ text: '15', value: '15' },
{ text: '30', value: '30' },
{ text: '45', value: '45' }
]
}
]
};
const picker = await this.pickerCtrl.create(opts);
picker.present();
picker.onDidDismiss().then(async data => {
console.log(data);
const hour = await picker.getColumn('hour');
const minute = await picker.getColumn('minute');
this.onChangeFinishTime((hour.options[hour.selectedIndex].value) as number, minute.options[minute.selectedIndex].value as number);
this.isPickerOpen = false;
});
let pickerAction;
const opts: PickerOptions = {
cssClass: 'time-picker',
buttons: [
{
text: 'Cancel',
role: 'cancel',
handler: value => {
pickerAction = 'cancel';
}
},
{
text: 'Done',
role: 'done',
handler: value => {
pickerAction = 'done';
}
}
],
columns: [
...
const picker = await this.pickerCtrl.create(opts);
picker.present();
picker.onDidDismiss().then(async data => {
if (pickerAction === 'done') {
const hour = await picker.getColumn('hour');
const minute = await picker.getColumn('minute');
this.onChangeFinishTime((hour.options[hour.selectedIndex].value) as number, minute.options[minute.selectedIndex].value as number);
}
this.isPickerOpen = false;
});
You need to move the logic from when the event onDidDismiss() is triggered (which means that the popover has disappeared, regardless of what action made it disappear) to the actual action of clicking the Done button.
This what the handler on Done does here, telling to set the value of the selected entry in the referenced column upon the popover dismissing as a consequence of clicking the Done button.
{data: undefined, role: undefined}
let opts: PickerOptions = {
cssClass: 'time-picker',
buttons: [
{
text: 'Cancel',
role: 'cancel'
},
{
text: 'Done',
handler: () => {
picker.dismiss().then(async data => {
console.log(data);
const hour = await picker.getColumn('hour');
const minute = await picker.getColumn('minute');
this.onChangeFinishTime((hour.options[hour.selectedIndex].value) as number, minute.options[minute.selectedIndex].value as number);
this.isPickerOpen = false;
});
}
}
],
columns: [
{
name: 'hour',
options: [
{ text: '01', value: '01' },
{ text: '02', value: '02' },
{ text: '03', value: '03' },
{ text: '04', value: '04' },
{ text: '05', value: '05' },
{ text: '06', value: '06' },
{ text: '07', value: '07' },
{ text: '08', value: '08' },
{ text: '09', value: '09' },
{ text: '10', value: '10' },
{ text: '11', value: '11' },
{ text: '12', value: '12' },
{ text: '13', value: '13' },
{ text: '14', value: '14' },
{ text: '15', value: '15' },
{ text: '16', value: '16' },
{ text: '17', value: '17' },
{ text: '18', value: '18' },
{ text: '19', value: '19' },
{ text: '20', value: '20' },
{ text: '21', value: '21' },
{ text: '22', value: '22' },
{ text: '23', value: '23' },
{ text: '24', value: '24' }
]
},
{
name: 'minute',
options: [
{ text: '00', value: '00' },
{ text: '15', value: '15' },
{ text: '30', value: '30' },
{ text: '45', value: '45' }
]
}
]
};
const picker = await this.pickerCtrl.create(opts);
picker.present();