Corresponding DropDownButtonFormFields in Flutter - flutter

I'm implementing corresponding dropdowns (where the options of the second dropdown depend on the first like so) that uses a list of objects in this format:
List<State> states = [
new State(stateId: 1, stateName: "New York", cities: [
new City(cityId: 1, cityName: "New York City"),
new City(cityId: 2, cityName: "Buffalo") ...
And the widget code is like so:
children: <Widget>[
DropdownButtonFormField<int>(
decoration: InputDecoration(labelText: 'State'),
value: selectedStateId,
items: states.map((State state) {
return new DropdownMenuItem<int>(
value: state.stateId,
child: new Text(states.singleWhere((x) => x.stateId == state.stateId).stateName),
);
}).toList(),
onChanged: (int newStateId) {
setState(() {
this.selectedCityId = states.singleWhere((x) => x.stateId == newStateId).cities[0].cityId; // set to first city for this state
this.selectedStateId = = newStateId;
});
},
),
DropdownButtonFormField<int>(
decoration: InputDecoration(labelText: 'City'),
value: selectedCityId,
items: states.singleWhere((x) => x.stateId == selectedStateId)
.cities
.map((City city) {
return new DropdownMenuItem<int>(
value: city.cityId,
child: new Text(states
.singleWhere((x) => x.stateId == selectedStateId).cities.singleWhere((x) => x.cityId == city.cityId).cityName),
);
}).toList(),
onChanged: (int newCityId) {
setState(() {
this.selectedCityId = newCityId;
});
},
)
],
When I change the State dropdown in this example, I get an error:
"There should be exactly one item with [DropdownButton]'s value: 1.
Either zero or 2 or more [DropdownMenuItem]s were detected with the same value".
The "1" in the above error corresponds to whatever the selected city value was prior to changing the state, so I know that the error relates to the fact that it's still looking for the old selectedCityId and it is no longer in the item list, but I'm not sure why as I've changed that value in setState. A key to this issue, I believe, is the same exact code works if I just change the DropDownButtonFormField to regular DropDownButtons, but I'd like to use the built in label text that comes along with the former.

Edit
You can use key: UniqueKey() int City DropdownButtonFormField
DropdownButtonFormField<int>(
key: UniqueKey(),
decoration: InputDecoration(labelText: 'City'),
You can copy paste run full code below
You can set selectedStateId and selectedCityId to states's attribute
You can not directly set to a value like selectedStateId = 1, because system will compare address
code snippet
int selectedStateId;
int selectedCityId;
#override
void initState() {
selectedStateId = states[0].stateId;
selectedCityId = states[0].cities[0].cityId;
super.initState();
}
working demo
full code
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class City {
int cityId;
String cityName;
City({this.cityId, this.cityName});
}
class CountryState {
int stateId;
String stateName;
List<City> cities;
CountryState({this.stateId, this.stateName, this.cities});
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
List<CountryState> states = [
CountryState(stateId: 1, stateName: " York", cities: [
City(cityId: 1, cityName: "York City"),
City(cityId: 2, cityName: "Buffalo")
]),
CountryState(stateId: 2, stateName: "A", cities: [
City(cityId: 3, cityName: "A1"),
City(cityId: 4, cityName: "A2")
])
];
int selectedStateId;
int selectedCityId;
#override
void initState() {
selectedStateId = states[0].stateId;
selectedCityId = states[0].cities[0].cityId;
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
DropdownButtonFormField<int>(
decoration: InputDecoration(labelText: 'State'),
value: selectedStateId,
items: states.map((CountryState state) {
return DropdownMenuItem<int>(
value: state.stateId,
child: Text(states
.singleWhere((x) => x.stateId == state.stateId)
.stateName),
);
}).toList(),
onChanged: (int StateId) {
setState(() {
this.selectedCityId = states
.singleWhere((x) => x.stateId == StateId)
.cities[0]
.cityId; // set to first city for this state
this.selectedStateId = StateId;
});
},
),
DropdownButtonFormField<int>(
key: UniqueKey(),
decoration: InputDecoration(labelText: 'City'),
value: selectedCityId,
items: states
.singleWhere((x) => x.stateId == selectedStateId)
.cities
.map((City city) {
return DropdownMenuItem<int>(
value: city.cityId,
child: Text(states
.singleWhere((x) => x.stateId == selectedStateId)
.cities
.singleWhere((x) => x.cityId == city.cityId)
.cityName),
);
}).toList(),
onChanged: (int CityId) {
setState(() {
this.selectedCityId = CityId;
});
},
)
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}

I posted this example on the Flutter issues board and they could not duplicate on the latest stable version (1.20.2 as of this comment). I upgraded my flutter version (I was on 1.17.1) and the same code ran without issue, so for anyone experiencing the same issue I suggest updating your flutter version.

Related

How to automatically select all items above the selected one flutter

I have a custom list view with selectable items.And I am trying to select all items automatically present above the one I selected. For Ex: Suppose there is 10 items in the list view and i selected 5th then it should select all the items available above 5th. i.e(1,2,3,4) and when i deselect 3rd item 1,2,3 items should deselected automatically
return CheckboxListTile(
activeColor: const Color.fromARGB(
255, 243, 243, 243),
checkColor: UIGuide.light_Purple,
selectedTileColor:
UIGuide.light_Purple,
value: value.selecteCategorys
.contains(value.feeList[index]
.installmentName ??
'--'),
onChanged: (bool? selected) async {
value.onFeeSelected(
selected!,
value.feeList[index]
.installmentName,
index,
value.feeList[index].netDue);
},
title: Text(
value.feeList[index].netDue ==
null
? '--'
: value.feeList[index].netDue
.toString(),
textAlign: TextAlign.end,
),
secondary: Text(
value.feeList[index]
.installmentName ??
'--',
),
);
do something like this :
1 - get index of selected item
2 - in the callback fun of checkbox do
let say we have list of items named by items
List<Item> items = [];
foo() {
final upperlist = items.getRange(0, index).toList();
upperlist.forEach((item) {item.selected =true });
items.replaceRange(0, index, upperlist);
setState((){});
}
Note, this example isn't perfect, but it's a working example that can get you thinking, as I don't know the bigger picture
Here's my approach:
get the widget and index of the currently selected value using .indexOf()
loop over all the widgets until the previously gotten index
for (var i = 0; i < _data.indexOf(item); i++) {
_data[i].isChecked = value!;
}
Code example
create a class called CheckBoxModel:
class CheckBoxModel {
bool isChecked = false;
String text = "";
CheckBoxModel({required this.isChecked, required this.text});
}
and then, generated 30 widgets:
final _data = List.generate(
30, (index) => CheckBoxModel(isChecked: false, text: "Item $index"));
and used it correspondingly:
Column(
children: [
for (var item in _data)
CheckboxListTile(
value: item.isChecked,
onChanged: (value) {
setState(() {
for (var i = 0; i < _data.indexOf(item); i++) {
_data[i].isChecked = value!;
}
});
},
title: Text(item.text),
),
],
)
Here's a complete runnable snipppet:
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class CheckBoxModel {
bool isChecked = false;
String text = "";
CheckBoxModel({required this.isChecked, required this.text});
}
final _data = List.generate(
30, (index) => CheckBoxModel(isChecked: false, text: "Item $index"));
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: Testing(),
),
),
);
}
}
class Testing extends StatefulWidget {
const Testing({Key? key}) : super(key: key);
#override
State<Testing> createState() => _TestingState();
}
class _TestingState extends State<Testing> {
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: [
for (var item in _data)
CheckboxListTile(
value: item.isChecked,
onChanged: (value) {
setState(() {
for (var i = 0; i < _data.indexOf(item); i++) {
_data[i].isChecked = value!;
}
});
},
title: Text(item.text),
),
],
),
);
}
}

How to print the selected item in a searchable dropdown box (from dropdown_search 5.0.3 package)?

I have a searchable dropdown box, from the package dropdown_search 5.0.3, where the choices in the dropdown box are titles mapped from a list I have created. When an option in the dropdown box is selected, I want to print the title and the corresponding 'amount' value of the option (from the list). However, I am having difficulty extracting the value of the dropdown box. I tried copying the code from some related questions that have been asked on here, but I'm getting the error 'The argument type 'void Function(String)' can't be assigned to the parameter type 'void Function(List< String >)?'. Where do I go from here?
Here is my current code:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My App',
theme: ThemeData(),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
typedef ValueChanged<T> = void Function(T value);
class _MyHomePageState extends State<MyHomePage> {
final _popupBuilderKey = GlobalKey<DropdownSearchState<String>>();
String dropdownSelected = '';
final List<Food> foodListData = [
Food(
title: 'Food 1',
id: 1,
amount: 3,
date: DateTime.now(),
),
Food(
title: "Food 2",
id: 2,
amount: 1,
date: DateTime.now(),
),
Food(
title: 'Food 3',
id: 3,
amount: 3,
date: DateTime.now(),
),
Food(
title: 'Food 4',
id: 4,
amount: 1,
date: DateTime.now(),
),
];
#override
Widget build(BuildContext context) {
final mediaQuery = MediaQuery.of(context);
final isLandscape =
MediaQuery.of(context).orientation == Orientation.landscape;
AppBar(
title: const Text(
'My App',
),
);
final pageBody = SafeArea(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Column(children: <Widget>[
Text(
'My Foods',
),
GestureDetector(
child: ElevatedButton(
child: Text("Add Food"),
onPressed: null,
),
),
DropdownSearch<String>.multiSelection(
key: _popupBuilderKey,
items: foodListData.map((item) {
return (item.title).toString();
}).toList(),
popupProps: PopupPropsMultiSelection.menu(
showSelectedItems: true,
showSearchBox: true,
),
onChanged: (String selectedValue) {
dropdownSelected = selectedValue;
}
)
])
],
)),
);
return Scaffold(
body: pageBody,
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: Platform.isIOS
? Container()
: FloatingActionButton(
child: Icon(Icons.add),
onPressed: null,
),
);
}
}
The multiSelection method returns a list of selected items and not a string. While, user may select multiple selections based on the search results that you need to take care of.
While this solution will assign the first selected value from the DropDown search result to the dropdownSelected variable.
change:
onChanged: (String selectedValue) {
dropdownSelected = selectedValue;
}
to:
onChanged: (List<String> selectedValue) {
dropdownSelected =
selectedValue.isNotEmpty ? selectedValue[0] : '';
}
You are providing different type of function in the onchanged.
Try this
onChanged: (String? selectedValue) {
dropdownSelected = selectedValue??'No Value';
}

Flutter Dropdown with sqllite

Good noon every one i want to ask on how to put a dropdown onchanged i am using sqllite for my database.
edit_note_page.dart
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
actions: [buildButton()],
),
body: Form(
key: _formKey,
child: NoteFormWidget(
category: category,
onChangedCategory: (category) => setState(() => this.category = category),
),
),
);
note_form_widget.dart
Widget buildCategory() => DropdownButton(
icon: const Icon(Icons.keyboard_arrow_down),
items: <String>['A1', 'A2', 'A3', 'A4','A5','C1']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: category,
child: Text(value),
);
}).toList(), onChanged: (String? value)
{
setState(() {
dropdownValue = newValue!;//im getting an error on this part
});
},
Logs
error encounter
The method 'setState' isn't defined for the type 'NoteFormWidget'.
Try correcting the name to the name of an existing method, or defining a method named 'setState'.
[{
"resource": "/c:/Users/VIMS-SERVER/Documents/Flutter Projects/apps/lib/widget/note_form_widget.dart",
"owner": "_generated_diagnostic_collection_name_#0",
"code": {
"value": "undefined_identifier",
"target": {
"$mid": 1,
"external": "https://dart.dev/diagnostics/undefined_identifier",
"path": "/diagnostics/undefined_identifier",
"scheme": "https",
"authority": "dart.dev"
}
},
"severity": 8,
"message": "Undefined name 'dropdownValue'.\nTry correcting the name to one that is defined, or defining the name.",
"source": "dart",
"startLineNumber": 229,
"startColumn": 11,
"endLineNumber": 229,
"endColumn": 24
}]
[{
"resource": "/c:/Users/VIMS-SERVER/Documents/Flutter Projects/apps/lib/widget/note_form_widget.dart",
"owner": "_generated_diagnostic_collection_name_#0",
"code": {
"value": "undefined_identifier",
"target": {
"$mid": 1,
"external": "https://dart.dev/diagnostics/undefined_identifier",
"path": "/diagnostics/undefined_identifier",
"scheme": "https",
"authority": "dart.dev"
}
},
"message": "Undefined name 'newValue'.\nTry correcting the name to one that is defined, or defining the name.",
}]
The setState method doesn't work on StatelessWidget because StatelessWidget doesn't have a state. Only StatefulWidget has a state, and therefore only it has a setState.
So you most turn your StatelessWidget to StatefulWidget.
I think your note_widget is stateless so you change to the stateful widget. you cant use a set state callback on the stateless widget.Dartpad live check here.you can use another state management tool(Provider ,cubit,riverport,bloc) to update your value
DropdownButton(
icon: const Icon(Icons.keyboard_arrow_down),
items: <String>['A1', 'A2', 'A3', 'A4', 'A5', 'C1']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
value: dropdownvalu,
onChanged: (values) {
setState(() {
dropdownvalu = values.toString();
});
},
)
Widget
class _ParentState extends State<Parent> {
Widget build(context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
IconButton(
onPressed: () {
setState(() {
counter++;
});
},
icon: const Icon(Icons.add),
),
],
),
body: Column(
children: [
DropdownButton(
icon: const Icon(Icons.keyboard_arrow_down),
items: <String>['A1', 'A2', 'A3', 'A4', 'A5', 'C1']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
value: dropdownvalu,
onChanged: (values) {
setState(() {
dropdownvalu = values.toString();
});
},
),
Center(
child: Text(
"$dropdownvalu",
style: TextStyle(fontSize: 30),
)),
],
),
);
}
}
SampleCode
import 'package:flutter/material.dart';
//import 'package:pucon/home.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Parent(),
);
}
}
class Parent extends StatefulWidget {
#override
State<Parent> createState() => _ParentState();
}
String dropdownvalu = "A1";
class _ParentState extends State<Parent> {
Widget build(context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
IconButton(
onPressed: () {
setState(() {
counter++;
});
},
icon: const Icon(Icons.add),
),
],
),
body: Column(
children: [
DropdownButton(
icon: const Icon(Icons.keyboard_arrow_down),
items: <String>['A1', 'A2', 'A3', 'A4', 'A5', 'C1']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
value: dropdownvalu,
onChanged: (values) {
setState(() {
dropdownvalu = values.toString();
});
},
),
Center(
child: Text(
"$dropdownvalu",
style: TextStyle(fontSize: 30),
)),
],
),
);
}
}
int counter = 0;
class Child extends StatefulWidget {
Child({Key? key}) : super(key: key);
#override
_ChildState createState() => _ChildState();
}
class _ChildState extends State<Child> {
#override
Widget build(BuildContext context) {
return Center(
child: Text(
"$dropdownvalu",
style: TextStyle(fontSize: 30),
));
} //to be incremented when the parent's button is clicked on.
}
// dbHelper
Future<List> getEmployeeData() async {
try {
final dbClient = await db;
var l = await dbClient!.transaction(
(txn) async => txn.rawQuery("SELECT * FROM ${DbConstants.tblGloEmployeeMaster} where is_active = 1"),
);
return l;
} catch (e) {
return [];
}
}
// getx
// login controller
// init
final employeeModelList = List<EmployeeModel>.empty(growable: true).obs;
// create method
void _getEmployees() async {
List list = await _dbHelper.getEmployeeData();
employeeModelList.value = [];
employeeModelList.value = list.map((employeeModel) => EmployeeModel.fromJson(employeeModel)).toList();
}
// create model
class EmployeeModel {
EmployeeModel({
required this.employeeId,
required this.employeeNm,
});
late final int employeeId;
late final String employeeNm;
EmployeeModel.fromJson(Map<String, dynamic> json) {
employeeId = json['employee_id'];
employeeNm = json['employee_nm'];
}
Map<String, dynamic> toJson() {
final _data = <String, dynamic>{};
_data['employee_id'] = employeeId;
_data['employee_nm'] = employeeNm;
return _data;
}
}
// stateless widget
// call
Container(
child: _searchEmployee(context),
),
// method
Widget _searchEmployee(BuildContext context) {
return Obx(
() => CustomSearchableDropDown(
items: _loginController.employeeModelList,
label: Strings.selectEmployee,
labelStyle: Theme.of(context).textTheme.bodyText1!.merge(TextStyles.defaultRegular),
dropdownLabelStyle: Theme.of(context).textTheme.bodyText1!.merge(TextStyles.defaultRegular),
dropDownMenuItems: _loginController.employeeModelList.map((item) {
return "${item.employeeId} - ${item.employeeNm}"; // ui view
}).toList(),
suffixIcon:
Icon(Icons.arrow_drop_down, size: Sizes.s16, color: Get.isDarkMode ? AppColors.white : AppColors.black),
decoration: BoxDecoration(border: Border(bottom: BorderSide(color: AppColors.fontGray))),
onChanged: (value) {
if (value != null) {
EmployeeModel employeeModel = value;
_loginController.employeeId.value = int.parse(employeeModel.employeeId);
_loginController.employeeName.value = employeeModel.employeeNm;
}
},
),
);
}

how can i create drowdownbutton with Riverpod Notifier?

I want to create DropDownButton with changenotifierProvider in Riverpod, but i can not write nicely my code. Please help me. I suppose, i just wrote 'watch' method, but i do not know how to read it. So, it should show the item which is chosen, and also it should be update with provider.Category.
My DropDownButton code is here:
Widget dropdownButton(BuildContext context,watch) {
String constantValue = "League Of Legends";
final postProvider = ChangeNotifierProvider<PostProvider>((ref) => PostProvider());
final provider = watch(postProvider);
return Consumer(
builder: (context, watch, _) {
return DropdownButton(
value: provider.postCategory ?? constantValue,
onChanged: (newValue) {
provider.postCategory = newValue;
},
items: <String>["League Of Legends", "Steam", "Csgo"]
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
onTap: () => value,
value: value ?? constantValue,
child: Text(value ?? constantValue),
);
}).toList());
},
);
}
Here my DropDownButton Image: ( when i choose any item of the list, it can not work properly. It always pick the first one (It picks "League of Legends").
I select steam but card categoty shows League of legends
final postProvider =
ChangeNotifierProvider<PostProvider>((ref) => PostProvider());
class PostProvider extends ChangeNotifier {
String _postCategory;
String get postCategory => _postCategory;
categoryOnChanged(String value) {
if (value.isEmpty) {
return _postCategory;
}
_postCategory = value;
print(_postCategory);
return notifyListeners();
}
}
class DropDownPage extends StatefulWidget {
#override
_DropDownPageState createState() => _DropDownPageState();
}
class _DropDownPageState extends State<DropDownPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Dropdown Riverpod issue"),
),
body: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: Center(
child: _DropDownWidgetConsumer(),
),
),
);
}
}
class _DropDownWidgetConsumer extends ConsumerWidget {
#override
Widget build(BuildContext context, ScopedReader watch) {
final category = watch(postProvider).postCategory;
return DropdownButton(
hint: Text("Choose category"),
value: category,
items: <String>["League Of Legends", "Steam", "Csgo"]
.map((e) => DropdownMenuItem<String>(
onTap: () => e,
value: e ?? category,
child: Text(e ?? "$category"),
))
.toList(),
onChanged: (value) {
context.read(postProvider).categoryOnChanged(value);
},
);
}
}

How can I handle a list of checkboxes dynamically created in flutter?

Using flutter, I am trying to build a list of values with some text and a customized checkbox next to it. Tapping anywhere on the text or checkbox should show the enabled state and tapping again should disable it. I am unsure how to handle the state of each checkbox separately. I tried using CheckBoxListTile too but I am not sure how I can achieve what I want. Can someone provide any examples?
Here's some sample code for CheckboxListTile. You can find more examples in the gallery.
import 'package:flutter/material.dart';
class Demo extends StatefulWidget {
#override
DemoState createState() => new DemoState();
}
class DemoState extends State<Demo> {
Map<String, bool> values = {
'foo': true,
'bar': false,
};
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text('CheckboxListTile demo')),
body: new ListView(
children: values.keys.map((String key) {
return new CheckboxListTile(
title: new Text(key),
value: values[key],
onChanged: (bool value) {
setState(() {
values[key] = value;
});
},
);
}).toList(),
),
);
}
}
void main() {
runApp(new MaterialApp(home: new Demo(), debugShowCheckedModeBanner: false));
}
I think it will work as you want. It also stores all selected checkbox value(s) into a List variable. so you please simply put this code in main.dart file and execute to check how it works.
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Multi-Select & Unselect Checkbox in Flutter'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List _selecteCategorys = List();
Map<String, dynamic> _categories = {
"responseCode": "1",
"responseText": "List categories.",
"responseBody": [
{"category_id": "5", "category_name": "Barber"},
{"category_id": "3", "category_name": "Carpanter"},
{"category_id": "7", "category_name": "Cook"}
],
"responseTotalResult":
3 // Total result is 3 here becasue we have 3 categories in responseBody.
};
void _onCategorySelected(bool selected, category_id) {
if (selected == true) {
setState(() {
_selecteCategorys.add(category_id);
});
} else {
setState(() {
_selecteCategorys.remove(category_id);
});
}
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: ListView.builder(
itemCount: _categories['responseTotalResult'],
itemBuilder: (BuildContext context, int index) {
return CheckboxListTile(
value: _selecteCategorys
.contains(_categories['responseBody'][index]['category_id']),
onChanged: (bool selected) {
_onCategorySelected(selected,
_categories['responseBody'][index]['category_id']);
},
title: Text(_categories['responseBody'][index]['category_name']),
);
}),
);
}
}
use List contains returns bool.
here is example
List<int> selectedList = [];
List<Widget> mList; //you can't add equal
createMenuWidget(Course courses) {
for (int b = 0; b < courses.length; b++) {
Map cmap = courses[b];
mList.add(CheckboxListTile(
onChanged: (bool value){
setState(() {
if(value){
selectedList.add(cmap[course_id]);
}else{
selectedList.remove(cmap[course_id]);
}
});
},
value: selectedList.contains(cmap[course_id]),
title: new Text(cmap[course_name]),
));
}
}
The simple Way to Do this with Dynamic List of Data with CheckBox.
List<String>data= ["Mathew","Deon","Sara","Yeu"];
List<String> userChecked = [];
ListView.builder(
itemCount: data.length,
itemBuilder: (context, i) {
return ListTile(
title: Text(
data[i])
trailing:Checkbox(
value: userChecked.contains(data[i]),
onChanged: (val) {
_onSelected(val, data[i]);
},
)
//you can use checkboxlistTile too
);
})
// now we write the functionality to check and uncheck it!!
void _onSelected(bool selected, String dataName) {
if (selected == true) {
setState(() {
userChecked.add(dataName);
});
} else {
setState(() {
userChecked.remove(dataName);
});
}
}
And Its Done !!...
Enjoy Fluttering...
Give a thumbs up as it will work for you !! :P
Please use package grouped_buttons.
It support both checkbox and radio.
https://pub.dartlang.org/packages/grouped_buttons
CheckboxGroup(
labels: <String>[
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
],
disabled: [
"Wednesday",
"Friday"
],
onChange: (bool isChecked, String label, int index) => print("isChecked: $isChecked label: $label index: $index"),
onSelected: (List<String> checked) => print("checked: ${checked.toString()}"),
),
and full example of usage in here https://github.com/akshathjain/grouped_buttons/blob/master/example/lib/main.dart
and author's logic to implement
https://github.com/akshathjain/grouped_buttons/blob/master/lib/src/checkbox_group.dart
Basically, author use two List of Strings to control selected and unselect
void onChanged(bool isChecked, int i){
bool isAlreadyContained = _selected.contains(widget.labels.elementAt(i));
if(mounted){
setState(() {
if(!isChecked && isAlreadyContained){
_selected.remove(widget.labels.elementAt(i));
}else if(isChecked && !isAlreadyContained){
_selected.add(widget.labels.elementAt(i));
}
if(widget.onChange != null) widget.onChange(isChecked, widget.labels.elementAt(i), i);
if(widget.onSelected != null) widget.onSelected(_selected);
});
}
}
Screenshot (Null safe)
Code:
class _MyPageState extends State<MyPage> {
final Map<String, bool> _map = {};
int _count = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () => setState(() => _map.addEntries([MapEntry('Checkbox #${++_count}', false)])),
),
body: ListView(
children: _map.keys
.map(
(key) => CheckboxListTile(
value: _map[key],
onChanged: (value) => setState(() => _map[key] = value!),
subtitle: Text(key),
),
)
.toList(),
),
);
}
}
Use chekboxListTile
Here is the sample code
#override
Widget build(BuildContext context) {
return Center(
child: CheckboxListTile(
title: Text('Check me'),
);
}
By the way, You can also add checkbox in ListView in Flutter. Apps sample is given below-
Main.dart
import 'package:flutter/material.dart';
import 'checkbox_in_listview_task-7.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(primarySwatch: Colors.blue,
),
home: CheckBoxInListview(),
);
}
}
checkbox_in_listview_task.dart
import 'package:flutter/material.dart';
class CheckBoxInListview extends StatefulWidget {
#override
_CheckBoxInListviewState createState() => _CheckBoxInListviewState();
}
class _CheckBoxInListviewState extends State<CheckBoxInListview> {
bool _isChecked = true;
List<String> _texts = [
"InduceSmile.com," "Flutter.io",
"google.com",
"youtube.com",
"yahoo.com",
"gmail.com"
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("CheckBox in ListView Example"),
),
body: ListView(
padding: EdgeInsets.all(8.0),
children: _texts.map((text) => CheckboxListTile(
title: Text(text),
value: _isChecked,
onChanged: (val) {
setState(() {
_isChecked = val;
});
},
)).toList(),
),
);
}
}
And here is the output
here how you can do it
import 'package:flutter/material.dart';
class RegisterFragments extends StatefulWidget {
RegisterFragments({Key key, this.step}) : super(key: key);
final int step;
_RegisterFragmentsState createState() => _RegisterFragmentsState();
}
class _RegisterFragmentsState extends State<RegisterFragments> {
Map<String, bool> values = {"abc": false, "def": true, "ghi": false};
List<String> _do = ['One', 'Two', 'Free', 'Four'];
String _dropdownValue = 'One';
#override
Widget build(BuildContext context) {
switch (widget.step) {
case 0:
return buildDo();
break;
case 1:
return Container(
child: ListView.builder(
shrinkWrap: true,
itemCount: values.length,
itemBuilder: (BuildContext context, int index) {
switch (widget.step) {
case 0:
return buildDo();
break;
case 1:
return buildService(context, index);
break;
default:
return Container();
break;
}
},
),
);
break;
default:
return Container();
break;
}
}
Widget buildService(BuildContext context, int index) {
String _key = values.keys.elementAt(index);
return Container(
child: Card(
child: CheckboxListTile(
title: Text(_key),
onChanged: (bool value) {
setState(() {
values[_key] = value;
});
},
value: values[_key],
),
),
);
}
Widget buildDo() {
return DropdownButton<String>(
isExpanded: true,
hint: Text("Service"),
items: _do.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
onChanged: (String newValue) {
setState(() {
this._dropdownValue = newValue;
});
},
value: _dropdownValue,
);
}
}
In case you are using the CheckBoxGroup or anything similar AND are inside a slider, do not forget to put it in a StatefulBuilder:
return StatefulBuilder(// StatefulBuilder
builder: (context, setState) {
return CheckboxGroup(
orientation: GroupedButtonsOrientation.HORIZONTAL,
margin: const EdgeInsets.only(left: 12.0),
onSelected: (List selected) => setState(() {
_checked = selected;
}),
labels: teamWorkoutDays,
checked: _checked,
itemBuilder: (Checkbox cb, Text txt, int i) {
return Column(
children: <Widget>[
Icon(Icons.polymer),
cb,
txt,
],
);
},
);
});