I want to create an evaluation app in flutter with multiple dropdownbuttons. The dropdownbuttons should contain a text with a value, for example: dropdownbutton1: "Text"; Value(2), dropdownbutton2: "Text"; Value2(4) and there is also an another button "evaluate", if i click on the "evaluate" button it should go to the next screen and the next screen displays the total of the value (it should be 6= value(2) + value2(4).
My next thought would be statemanagement, but i dont know how to do it right now.
I searched everywhere in the internet but couldnt find anything.
I am new to flutter. Is there a way to do it with statemanagement and how it could be look like?
Definitely you should implement a flavor of state management, both for the communication between the pages as well as to feed data to the dropdown menus, and holding on to the selected values from the dropdowns.
My suggestion would be to go with something as simple as the Provider state management strategy, and leverage the widgets that facilitate listening to changes occurring on the application. This strategy makes your app more decouples, maintains a clean separation of concerns and allows for good maintenance.
You can create a Provided service (i.e. DropdownService) that holds to the values of the dropdown menus as a list of dropdown options, as well as two properties that hold on to the selected values from the dropdowns (i.e. selectedFirstOption, selectedSecondOption). Upon triggering changes on both DropDownButton widgets, you can trigger a notification for the widget to rebuild itself, updating its selections, and holding on to the selected value.
A button will trigger the evaluation and navigation to the next page, only if both selectedFirstOption and selectedSecondOption are not null, then the next page also consumes the provided DropdownService, pulls the data persisted for both selections, add the values and displays it to the user.
I threw something together as an example to illustrate my point below:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(
create: (_) => DropdownService()
)
],
child: MyApp()
)
);
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Consumer<DropdownService>(
builder: (context, dropdownService, child) {
return Container(
padding: const EdgeInsets.all(30),
child: Column(
children: [
const Text('First dropdown:'),
DropdownButton<DropdownOption>(
value: dropdownService.selectedFirstOption,
icon: const Icon(Icons.arrow_drop_down),
elevation: 16,
onChanged: (DropdownOption? newValue) {
dropdownService.selectedFirstOption = newValue!;
},
items: dropdownService.firstDropdown.map((DropdownOption option) {
return DropdownMenuItem<DropdownOption>(
value: option,
child: Text(option.text!),
);
}).toList(),
),
const SizedBox(height: 20),
const Text('Second dropdown:'),
DropdownButton<DropdownOption>(
value: dropdownService.selectedSecondOption,
icon: const Icon(Icons.arrow_drop_down),
elevation: 16,
onChanged: (DropdownOption? newValue) {
dropdownService.selectedSecondOption = newValue!;
},
items: dropdownService.secondDropdown.map((DropdownOption option) {
return DropdownMenuItem<DropdownOption>(
value: option,
child: Text(option.text!),
);
}).toList(),
),
const SizedBox(height: 20),
Material(
color: Colors.amber,
child: TextButton(
onPressed: dropdownService.selectedFirstOption != null
&& dropdownService.selectedSecondOption != null ? () {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => NextPage())
);
} : null,
child: const Text('Evaluate', style: TextStyle(color: Colors.black)
)
)
)
]
)
);
}
);
}
}
class NextPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
DropdownService dropdownService = Provider.of<DropdownService>(context, listen: false);
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('The result of ${dropdownService.selectedFirstOption!.text!} and ${dropdownService.selectedSecondOption!.text!}:'),
const SizedBox(height: 20),
Text('${dropdownService.selectedFirstOption!.value! + dropdownService.selectedSecondOption!.value!}',
style: const TextStyle(fontSize: 50)
),
],
),
),
);
}
}
class DropdownService extends ChangeNotifier {
List<DropdownOption> firstDropdown = [
DropdownOption(text: 'Value (5)', value: 5),
DropdownOption(text: 'Value (6)', value: 6),
DropdownOption(text: 'Value (7)', value: 7),
];
DropdownOption? _selectedFirstOption; // = DropdownOption(text: 'Select Value', value: -1);
DropdownOption? _selectedSecondOption; // = DropdownOption(text: 'Select Value', value: -1);
DropdownOption? get selectedFirstOption => _selectedFirstOption;
DropdownOption? get selectedSecondOption => _selectedSecondOption;
set selectedFirstOption(DropdownOption? value) {
_selectedFirstOption = value;
notifyListeners();
}
set selectedSecondOption(DropdownOption? value) {
_selectedSecondOption = value;
notifyListeners();
}
List<DropdownOption> secondDropdown = [
DropdownOption(text: 'Value (1)', value: 1),
DropdownOption(text: 'Value (2)', value: 2),
DropdownOption(text: 'Value (3)', value: 3),
];
}
class DropdownOption {
String? text;
double? value;
DropdownOption({ this.text, this.value });
}
If you run this code (also provided as a Gist) through DartPad.dev, you should see the following output:
Related
I am creating a form with the plugin flutter_form_builder (https://pub.dev/packages/flutter_form_builder).
When I use FormBuilderDropdown, you can selected a different value, but it won't show you the selected value on screen. Normally you have a value property, but this widget does not have that. It only has an initial value.
Note
When I removed the whole onChanged method, it does show me the right value on the screen. BUT I need this onChanged method so I cannot remove it...
Code from
final shippingPackagesList = [
{"key": "dhlpwc-parcelshop", "label": "DHL ServicePoint"},
{"key": "dhlpwc-home", "label": "Thuis bezorgen"},
{
"key": "local_pickup:7",
"label": "Afhalen in de winkel in Heerlen, Limburg"
},
];
return Column(
children: [
FormBuilder(
autovalidateMode: AutovalidateMode.always,
key: _formKey,
child: Column(
children: [
const SizedBox(height: 5.0),
FormBuilderDropdown(
items: shippingPackagesList
.map((shippingPackage) =>
DropdownMenuItem(
value: shippingPackage['key'],
child: Text(shippingPackage['label']!),
))
.toList(),
name: 'shipping_key',
onChanged: (value) {
String shippingPackageKey =
value.toString();
// Set selected shipping method in cart view model
cartViewModel
.setSelectedShippingPackageByString(
shippingPackageKey);
cartViewModel.updateTotalCosts();
},
// initialValue: "dhlpwc-parcelshop",
hint: Text("Kies verzendmethode"),
decoration: const InputDecoration(
border: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.zero)),
contentPadding: EdgeInsets.all(8.0),
)),
const SizedBox(height: 10.0),
],
)),
Text(
'€ ${cartViewModel.selectedShippingPackage!.totalCost.toStringAsFixed(2)}',
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
]
)
How can I solve this problem? Or is this a bug?
EDIT
Cart view model functions
class CartViewModel extends ChangeNotifier {
// Properties
ShippingPackage? _selectedShippingPackage;
double? _totalWithShippingPrice;
// Getters
ShippingPackage? get selectedShippingPackage => _selectedShippingPackage;
double? get totalWithShippingPrice => _totalWithShippingPrice;
void setSelectedShippingPackageByString(String shippingPackageKey) {
for (var shippingPackage in cart!.shippingPackages) {
if (shippingPackage.key == shippingPackageKey) {
_selectedShippingPackage = shippingPackage;
}
}
notifyListeners();
}
void updateTotalCosts() {
double total =
cart!.totals.articlesWithTax + selectedShippingPackage!.totalCost;
_totalWithShippingPrice = total;
notifyListeners();
}
}
Main
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => CartViewModel()),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'App',
home: Scaffold(
body: MyMainHome(),
),
),
);
}
Pubspec yaml
add provider: ^6.0.2 in pubspec.yaml
I experimented with the flutter_form_builder and the FormBuilderDropdown specifically. Writing this code based on the example of the package:
class Home72124205 extends StatefulWidget {
const Home72124205({Key? key}) : super(key: key);
#override
State<Home72124205> createState() => _Home72124205State();
}
class _Home72124205State extends State<Home72124205> {
List<String> locationsList = [
'New York',
'Tokyo',
'London',
];
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FormBuilderDropdown(
name: 'location',
decoration: const InputDecoration(
labelText: 'Location',
),
initialValue: locationsList.first,
allowClear: true,
onChanged: (value){
print(value);
},
items: locationsList
.map((location) => DropdownMenuItem(
value: location,
child: Text(location),
)).toList(),
),
),
);
}
}
I was not able to reproduce your issue. The widget works as intended. The label on the dropdown changes, the onChange gets called and the code gets executed.
As we don't have access to your full application, I am unable debug your issue.
Are you able to experiment with this example and test if, within the context of your application, the problem still happens?
I have a code that is responsible for filtering by certain categories (I shortened it for ease of reading). When opening the filter window, the user sees these category names ('Select a brand', 'Select a operation system', 'Select a color' etc).
Next, the user can open the category (initially, the dropdown list is in the closed position.), and select the parameters from the drop-down list (and click the apply button). The next time you open the filter window, the checkboxes in front of the parameters remain, but the drop-down list collapses.
Tell me how to do it: if in any category there are options marked with a checkmark, so that the drop-down list will be open the next time the window with filters is opened.
class FilterDialog extends StatefulWidget {
final void Function(Map<String, List<String>?>) onApplyFilters;
final Map<String, List<String>?> initialState;
const FilterDialog({
Key? key,
required this.onApplyFilters,
this.initialState = const {},
}) : super(key: key);
#override
State<FilterDialog> createState() => _FilterDialogState();
}
class _FilterDialogState extends State<FilterDialog> {
// Temporary storage of filters.
Map<String, List<String>?> filters = {};
bool needRefresh = false;
// Variable for the ability to hide all elements of filtering by any parameter.
bool isClickedBrand = false;
List manufacturer = [];
#override
void initState() {
super.initState();
filters = widget.initialState;
}
// A function to be able to select an element to filter.
void _handleCheckFilter(bool checked, String key, String value) {
final currentFilters = filters[key] ?? [];
if (checked) {
currentFilters.add(value);
} else {
currentFilters.remove(value);
}
setState(() {
filters[key] = currentFilters;
});
}
// Building a dialog box with filters.
#override
Widget build(BuildContext context) {
return SimpleDialog(
// Window title.
title: const Text('Filters',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.w600,
)),
contentPadding: const EdgeInsets.all(16),
// Defining parameters for filtering.
children: [
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Here and in subsequent Column, there will be a definition of parameters for filtering,
// a title, the ability to hide/show the items of list
Column(children: [
InkWell(
onTap: () async {
manufacturer = await getManufacturerOptions();
setState(() {
isClickedBrand = !isClickedBrand;
});
},
child: Row(children: [
Text('Select a brand'.toString(),
style: const TextStyle(
fontSize: 18,
)),
const Spacer(),
isClickedBrand
? const Icon(Icons.arrow_circle_up)
: const Icon(Icons.arrow_circle_down)
])),
!isClickedBrand
? Container()
: Column(
children: manufacturer
.map(
(el) => CustomCheckboxTile(
value: filters['manufacturer']?.contains(el) ??
false,
label: el,
onChange: (check) =>
_handleCheckFilter(check, 'manufacturer', el),
),
)
.toList())
]),
const SizedBox(
height: 5,
),
// Building a button to apply parameters.
const SizedBox(
height: 10,
),
ElevatedButton(
onPressed: () {
Navigator.of(context).pop();
widget.onApplyFilters(filters);
needRefresh = true;
},
child:
const Text('APPLY', style: TextStyle(color: Colors.black)),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.grey),
)),
// Building a button to reset parameters.
const SizedBox(
height: 5,
),
ElevatedButton(
onPressed: () async {
setState(() {
filters.clear();
});
widget.onApplyFilters(filters);
},
child: const Text('RESET FILTERS',
style: TextStyle(color: Colors.black)),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.grey),
)),
],
),
],
);
}
}
For example: the user clicks on the filter box, selects the brands to search for, and clicks the apply button. My task is that the next time the user opens the filter window, the categories with active checkboxes (in this example, the brand) are in an expanded state
The concept is, you need to check filter data with while opening dialog, To simplify the process I am using ExpansionTile. You can check this demo and customize the behavior and look.
Run on dartPad, Click fab to open dialog and touch outside the dialog to close this.
class ExTExpample extends StatefulWidget {
ExTExpample({Key? key}) : super(key: key);
#override
State<ExTExpample> createState() => _ExTExpampleState();
}
class _ExTExpampleState extends State<ExTExpample> {
// you can use map or model class or both,
List<String> filter_data = [];
List<String> brands = ["Apple", "SamSung"];
List<String> os = ["iOS", "Android"];
_showFilter() async {
await showDialog(
context: context,
builder: (c) {
// you can replace [AlertDialog]
return AlertDialog(
content: StatefulBuilder(
builder: (context, setSBState) => SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ExpansionTile(
title: const Text("Brand"),
/// check any of its's item is checked or not
initiallyExpanded: () {
// you can do different aproach
for (final f in brands) {
if (filter_data.contains(f)) return true;
}
return false;
}(),
children: [
...brands.map(
(brandName) => CheckboxListTile(
value: filter_data.contains(brandName),
title: Text(brandName),
onChanged: (v) {
if (filter_data.contains(brandName)) {
filter_data.remove(brandName);
} else {
filter_data.add(brandName);
}
setSBState(() {});
//you need to reflect the main ui, also call `setState((){})`
},
),
),
],
),
ExpansionTile(
title: const Text("select OS"),
/// check any of its's item is checked or not
initiallyExpanded: () {
// you can do different aproach
for (final f in os) {
if (filter_data.contains(f)) return true;
}
return false;
}(),
children: [
...os.map(
(osName) => CheckboxListTile(
value: filter_data.contains(osName),
title: Text(osName),
onChanged: (v) {
if (filter_data.contains(osName)) {
filter_data.remove(osName);
} else {
filter_data.add(osName);
}
setSBState(() {});
//you need to reflect the main ui, also call `setState((){})`
},
),
),
],
),
],
),
),
),
);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FloatingActionButton(
onPressed: () {
_showFilter();
},
),
),
);
}
}
Whenever you open filter the isClickedBrand is False so it won't showed you a list. So the solution is :
After selecting option from list, change the state of isClickedBrand state. I mean if it's true then it will show the list otherwise show container.
Hope you get my point.
EDIT: Im retarded, i figured it out
used the widget. to get access to the class variable
swapped out the Text("fsfd); for my list variable resulting in
child: Consumer<WidgetDataNotify>(
builder: (context,datatonotify,child){
print("value == ${datatonotify.value}");
return FuctionListSet[datatonotify.value];
},
child: Text("${provtest.value}"),
i've been following
Flutter provider state not updating in consumer widget
to try and understand the process along with the documentation and videos ect ect.
and i cannot figure out how to ensure im using the same instance of a provider across classes (dart files)
My program is composed of widgets and a radiolist that when it's clicked will update the provider to it's index value which then from a list in my main (thats wrapped) in a consumer will update depending on the interger affecting the list
provider file:
class WidgetDataNotify extends ChangeNotifier {
int value=0;
//int get grabvalue => value;
// Widget SelectedWidget=SingleButtonMovementFunction();
// Widget get pickedWidget =>SelectedWidget=FuctionListSet[value];
void UpdateWidgetList(int picker){
value = picker;
print("updated value to $value");
notifyListeners();
}
}
RadioList code: Problem here is i dont know how to communicate that provider value i've passed in
class RadioListBuilder extends StatefulWidget {
final int num;
static int value=0;
final WidgetDataNotify provider;
const RadioListBuilder({Key key, this.num,this.provider}) : super(key: key);
#override
RadioListBuilderState createState() {
return RadioListBuilderState();
}
}
class RadioListBuilderState extends State<RadioListBuilder> {
static int test;
int _value;
#override
Widget build(BuildContext context) {
return ListView.builder(
itemBuilder: (context, index) {
return Column(
children: [
Container(
height: 60,
width: MediaQuery.of(context).size.width,
color: Colors.brown[800],
child: RadioListTile(
selectedTileColor: Colors.amber,
activeColor: Colors.amber,
tileColor: Colors.black54,
value: index,
groupValue: _value,
onChanged: (x) => setState((){
_value = x;
///provider.UpdateWidgetList(x); /// providing the value to the provider
///ideally would call the function
Activated_Function_Selected=index;
print("Activated fuction is indexed at $Activated_Function_Selected and it's name is == ${FunctionList[index].characters}");
}),
title: Text("${FunctionList[index]}",style: TextStyle(color: Colors.white,fontSize: 18,),softWrap: true,maxLines: 2,),
),
),
Divider(color: Colors.black,height: 10,thickness: 10,),
],
);
},
itemCount: widget.num,
);
}
}
Start of my main function has this to ensure the context would be the same
#override
Widget build(BuildContext context) {
WidgetDataNotify provtest = Provider.of<WidgetDataNotify>(context,listen: true);
return Scaffold(
appBar: AppBar(
i pass this on into my radio list
Expanded(
flex:2 ,
child: Container(
color: Colors.deepPurple,
child: RadioListBuilder(num: FunctionList.length,provider: provtest,),
),
),
then i have my consumer listen out for it
Expanded(
flex: 3,
child: Container(
color: Colors.orangeAccent,
//
// child: Selector<WidgetDataNotify, int>(
// selector: (context,model) => model.value,
// builder: (context,value,child){
// print("accesed value==$value");
// return Center(
// child: FuctionListSet[value],
// );
// },
// child: Text("AAAAAAAAAAAAAAAAAAAAAAAAAAAA"),
// ),
child: Consumer<WidgetDataNotify>(
builder: (context,datatonotify,child){
print("value == ${datatonotify.value}");
testA=datatonotify.value;
print("test == $testA");
return Text("faf");
},
child: Text("${provtest.value}"),
),
),
//),),
),
How do I populate this array list into a dropdown button?
I want to populate this list of the location to the dropdown button.
[here is how my database looks like]
https://i.stack.imgur.com/S5yDh.png
I know, it's too late to answer your question. But maybe, mine is for anybody who seeks an answer.
Just use streambuilder to stream firestore data in your dropdown.
Here is my example:
StreamBuilder(
stream: Firestore.instance.collection('your collectionName').document('yourDocument').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return textCustom('Loading', Colors.black87, 16, 'Montserrat');
} else {
final data = snapshot.data['data'];
return Theme(
data: Theme.of(context).copyWith(
canvasColor: Color(0xFF221F1F),
),
child: DropdownButtonFormField(
style: TextStyle(color: Colors.white70),
value: _value,
items: data
.map<DropdownMenuItem<String>>(
(x) => DropdownMenuItem(
child: textCustom(
x, Colors.white, 16, 'Montserrat'),
value: '${x}',
),
)
.toList(),
onChanged: (val) => setState(() {
_value = val;
}),
),
);
}
},
)
I recommend the flutter_form_bloc package. It's very helpful and you can asynchronously add items to a dropdown array so you can fetch them from an API or for your needs, Firebase.
If you do not want to use a package however, you could create an empty list and assign it to the items parameter initially. In your initState method, you could then populate that list with items and then call setState.
This is not the best way, but gets the work done.
Create a temporary list, then use that list to do a for each.
tempList = returnedDoc['location'];
tempList.forEach((element) {
Locations.add(element);
}),
You can create a dropdown button in following way.
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(
home: MyApp(),
));
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String dropdownValue;
List<String> listOfStrings = ["apple", "banana", "strawberry", "cherry"];
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: DropdownButton<String>(
value: dropdownValue,
icon: Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (String newValue) {
setState(() {
dropdownValue = newValue;
});
},
items: listOfStrings.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
),
);
}
}
enter code herehey all of master , i have code for filter data on api json, i want my user can select specific teacher by specific locatioin on drop down. the search by name are already work, but the dropdown i don't know how to implement it, to take effect on my json api slection.
here is my code
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
title: "Para Dai",
home: new DropDown(),
));
}
class DropDown extends StatefulWidget {
DropDown() : super();
// end
final String title = "DropDown Demo";
#override
DropDownState createState() => DropDownState();
}
class Province {
int id;
String name;
Province(this.id, this.name);
static List<Province> getProvinceList() {
return <Province>[
Province(1, 'Central Java'),
Province(2, 'East kalimantan'),
Province(3, 'East java'),
Province(4, 'Bali'),
Province(5, 'Borneo'),
];
}
}
// ADD THIS
class District {
int id;
String name;
District(this.id, this.name);
static List<District> getDistrictList() {
return <District>[
District(1, 'Demak'),
District(2, 'Solo'),
District(3, 'Sidoarjo'),
District(4, 'Bandung'),
];
}
}
class DropDownState extends State<DropDown> {
String finalUrl = '';
List<Province> _provinces = Province.getProvinceList();
List<DropdownMenuItem<Province>> _dropdownMenuItems;
Province _selectedProvince;
// ADD THIS
List<District> _disctricts = District.getDistrictList();
List<DropdownMenuItem<District>> _dropdownMenuDistricts;
District _selectedDistrict;
#override
void initState() {
_dropdownMenuItems = buildDropdownMenuItems(_provinces);
_dropdownMenuDistricts = buildDropdownDistricts(_disctricts); // Add this
_selectedProvince = _dropdownMenuItems[0].value;
_selectedDistrict = _dropdownMenuDistricts[0].value; // Add this
super.initState();
}
List<DropdownMenuItem<Province>> buildDropdownMenuItems(List provinceses) {
List<DropdownMenuItem<Province>> items = List();
for (var province in provinceses) {
items.add(
DropdownMenuItem(
value: province,
child: Text(province.name),
),
);
}
return items;
}
// ADD THIS
List<DropdownMenuItem<District>> buildDropdownDistricts(
List<District> districts) {
List<DropdownMenuItem<District>> items = List();
for (var district in districts) {
items.add(
DropdownMenuItem(
value: district,
child: Text(district.name),
),
);
}
return items;
}
onChangeDropdownItem(Province newProvince) {
// Add this
final String url =
'https://onobang.com/flutter/index.php?province=${newProvince.name}&district=${_selectedDistrict.name}';
setState(() {
_selectedProvince = newProvince;
finalUrl = url; // Add this
});
}
onChangeDistrict(District newDistrict) {
// Add this
final String url =
'https://onobang.com/flutter/index.php?province=${_selectedProvince.name}&district=${newDistrict.name}';
setState(() {
_selectedDistrict = newDistrict;
finalUrl = url; // Add this
});
}
#override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
home: new Scaffold(
appBar: new AppBar(
title: new Text("DropDown Button Example"),
),
body: new Container(
margin: const EdgeInsets.all(0.0),
padding: const EdgeInsets.all(13.0),
child: new Column(
children: <Widget>[
new Container(
margin: const EdgeInsets.all(0.0),
padding: const EdgeInsets.all(13.0),
decoration: new BoxDecoration(
border: new Border.all(color: Colors.blueGrey)),
child: new Text(
"Welcome to teacher list app, please select teacher by province / district and name"),
),
new Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("Prov : "),
SizedBox(
height: 20.0,
),
DropdownButton(
value: _selectedProvince,
items: _dropdownMenuItems,
onChanged: onChangeDropdownItem,
),
SizedBox(
height: 20.0,
),
// Text('Selected: ${_selectedProvince.name}'),
// SizedBox(
// height: 20.0,
// ),
Text(" Dist : "),
SizedBox(
height: 20.0,
),
DropdownButton(
value: _selectedDistrict,
items: _dropdownMenuDistricts,
onChanged: onChangeDistrict,
),
SizedBox(
height: 20.0,
),
// Text('Selected: ${_selectedDistrict.name}'),
// SizedBox(
// height: 20.0,
// ),
// Padding(
// padding: const EdgeInsets.all(8.0),
// child: Text('$finalUrl'),
// ),
],
),
new Card(
child: new Center(
child: TextFormField(
decoration: InputDecoration(labelText: 'Teacher Name'),
))),
new FlatButton(
color: Colors.blue,
textColor: Colors.white,
disabledColor: Colors.grey,
disabledTextColor: Colors.black,
padding: EdgeInsets.all(8.0),
splashColor: Colors.blueAccent,
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondWidget(value:"$finalUrl"))
);
// what action to show next screen
},
child: Text(
"Show List",
),
),
],
),
),
),
);
}
}
// ignore: must_be_immutable
class SecondWidget extends StatelessWidget
{
String value;
SecondWidget({Key key, #required this.value}):super(key:key);
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(title: Text("Page 2"),),
body: Column(children: <Widget>[
Text("I wish Show JSON Mysql listview with this URL : "+this.value),
RaisedButton(child: Text("Go Back"),
onPressed: () {
Navigator.pop(context);
}),
],)
);
}
}
any help very thanks before iam a beginner in flutter, and very dificult to learn flutter
Edit
If you mean click Menu Item and change _buildSearchResults's content,
your _buildSearchResults is based on List _searchResult, modify content as you do in onSearchTextChanged will work. In RaisedButton, you can do this with onPressed
RaisedButton(
padding: const EdgeInsets.all(8.0),
textColor: Colors.white,
color: Colors.blue,
onPressed: (newDistrict) {
setState(() {
_myDistrict = newDistrict;
_searchResult.clear();
//recreate your _searchResult again.
});
},
child: new Text("Submit"),
)
onChanged: (newDistrict) {
setState(() {
_myDistrict = newDistrict;
_searchResult.clear();
//recreate your _searchResult again.
});
},
If I understand you clear, you are trying to create DropdownMenuItem via JSON string get from API.
JSON from different API, you can join them
List<Map> _jsonApi1 = [
{"id": 0, "name": "default 1"}
];
List<Map> _jsonApi2 = [
{"id": 1, "name": "second 2"},
{"id": 2, "name": "third 3"}
];
List<Map> _myJson = new List.from(_jsonApi1)..addAll(_jsonApi2);
Generate menuitem
new DropdownButton<String>(
isDense: true,
hint: new Text("${_jsonApi1[0]["name"]}"),
value: _mySelection,
onChanged: (String newValue) {
setState(() {
_mySelection = newValue;
});
print(_mySelection);
},
items: _myJson.map((Map map) {
return new DropdownMenuItem<String>(
value: map["id"].toString(),
child: new Text(
map["name"],
),
);
}).toList(),
full code
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
List<Map> _jsonApi1 = [
{"id": 0, "name": "default 1"}
];
List<Map> _jsonApi2 = [
{"id": 1, "name": "second 2"},
{"id": 2, "name": "third 3"}
];
List<Map> _myJson = new List.from(_jsonApi1)..addAll(_jsonApi2);
class _MyHomePageState extends State<MyHomePage> {
String _mySelection;
#override
Widget build(BuildContext context) {
return new Scaffold(
body: SafeArea(
child: Column(
children: <Widget>[
Container(
height: 500.0,
child: new Center(
child: new DropdownButton<String>(
isDense: true,
hint: new Text("${_jsonApi1[0]["name"]}"),
value: _mySelection,
onChanged: (String newValue) {
setState(() {
_mySelection = newValue;
});
print(_mySelection);
},
items: _myJson.map((Map map) {
return new DropdownMenuItem<String>(
value: map["id"].toString(),
child: new Text(
map["name"],
),
);
}).toList(),
),
),
),
],
),
),
);
}
}