I'm trying to adapt some code to sort on a multidimensional array.
But I can't recreate the filtered array to retrieve the sets of elements.
Here is the original code:
import 'package:flutter/material.dart';
class TestPage extends StatefulWidget {
#override
_TestPageState createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> {
TextEditingController _textController = TextEditingController();
List<String> initialList = ["Chat", "Chien", "Rat", "Cheval", "Ours"];
List<String> filteredList = List();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Test search')),
body: Column(
children: <Widget>[
TextField(
controller: _textController,
onChanged: (text) {
text = text.toLowerCase();
setState(() {
filteredList = initialList
.where((element) => element.toLowerCase().contains(text))
.toList();
});
},
),
if (filteredList.length == 0 && _textController.text.isEmpty)
Expanded(
child: ListView.builder(
itemCount: initialList.length,
itemBuilder: (BuildContext context, index) {
return Container(
height: 50,
child: Text(initialList[index]),
);
}))
else if (filteredList.length==0 && _textController.text.isNotEmpty)
Expanded(
child: Container(
child: Text('Aucune donnée'),
),
)
else
Expanded(
child: ListView.builder(
itemCount: filteredList.length,
itemBuilder: (BuildContext context, index) {
return Container(
height: 50,
child: Text(filteredList[index]),
);
}),
),
],
));
}
}
And my modified code:
import 'package:flutter/material.dart';
class Houblons extends StatefulWidget {
#override
_HoublonsState createState() => _HoublonsState();
}
class _HoublonsState extends State<Houblons> {
TextEditingController _textController = TextEditingController();
//List<String> initialList = ["Chat", "Chien", "Rat", "Cheval", "Ours"];
List<ListeElements> initialList = [
new ListeElements (nom : "testa", lienp: 1),
new ListeElements (nom : "testaa", lienp: 2),
new ListeElements (nom : "testaa b", lienp: 2),
new ListeElements (nom : "testaa bb", lienp: 2),
new ListeElements (nom : "testaa bb c", lienp: 2),
];
List<ListeElements2> filteredList = List();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Houblons')),
body: Column(
children: <Widget>[
TextField(
controller: _textController,
onChanged: (text) {
text = text.toLowerCase();
setState(() {
filteredList = initialList
.where((element) => element.nom.contains(text)).cast<String>()
.toList();
});
},
decoration: new InputDecoration(
labelText: "Champ de recherche",
),
),
if (filteredList.length == 0 && _textController.text.isEmpty)
Expanded(
child: ListView.builder(
itemCount: initialList.length,
itemBuilder: (BuildContext context, index) {
return Container(
height: 50,
child: Text(initialList[index].nom),
);
}))else if (filteredList.length==0 && _textController.text.isNotEmpty)
Expanded(
child: Container(
child: Text('Aucune donnée'),
),
)else
Expanded(
child: ListView.builder(
itemCount: filteredList.length,
itemBuilder: (BuildContext context, index) {
return Container(
height: 50,
child: Text(filteredList[index].nom),
);
}),
),
],
));
}
}
class ListeElements {
String nom;
int lienp;
ListeElements({String nom, int lienp}){
this.nom = nom;
this.lienp = lienp;
}
}
class ListeElements2 {
String nom;
int lienp;
ListeElements2({String nom, int lienp}){
this.nom = nom;
this.lienp = lienp;
}
}
I planned after to make a listview with a link on each element which will display an alert with elements coming from the multidimensional table.
Thank you for your help.
Thanks, but I can't.
I found some code that works with a json list from an online list, but when that created the list its not working.
I can't find the mistake I'm making,
Yet I think it's simple but I'm blocking.
I can't find an example code online
The original code:
a link!
here is my code:
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
class TestFilter extends StatefulWidget {
TestFilter() : super();
final String title = "Filter List Demo";
#override
TestFilterState createState() => TestFilterState();
}
class Debouncer {
final int milliseconds;
VoidCallback action;
Timer _timer;
Debouncer({this.milliseconds});
run(VoidCallback action) {
if (null != _timer) {
_timer.cancel();
}
_timer = Timer(Duration(milliseconds: milliseconds), action);
}
}
class TestFilterState extends State<TestFilter> {
final _debouncer = Debouncer(milliseconds: 500);
List<User> filteredUsers = List();
List<User> users = [
{'id': 40, 'name': "moia", 'email': "test#1.com"},
{'id': 40, 'name': "moiaa", 'email': "test#2.com"},
{'id': 40, 'name': "moiab", 'email': "test#3.com"},
];
#override
void initState() {
super.initState();
setState(() {
users = filteredUsers;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children: <Widget>[
TextField(
decoration: InputDecoration(
contentPadding: EdgeInsets.all(15.0),
hintText: 'Filter by name or email',
),
onChanged: (string) {
_debouncer.run(() {
setState(() {
filteredUsers = users
.where((u) => (u.name
.toLowerCase()
.contains(string.toLowerCase()) ||
u.email.toLowerCase().contains(string.toLowerCase())))
.toList();
});
});
},
),
Expanded(
child: ListView.builder(
padding: EdgeInsets.all(10.0),
itemCount: filteredUsers.length,
itemBuilder: (BuildContext context, int index) {
return Card(
child: Padding(
padding: EdgeInsets.all(10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
filteredUsers[index].name,
style: TextStyle(
fontSize: 16.0,
color: Colors.black,
),
),
SizedBox(
height: 5.0,
),
Text(
filteredUsers[index].email.toLowerCase(),
style: TextStyle(
fontSize: 14.0,
color: Colors.grey,
),
),
],
),
),
);
},
),
),
],
),
);
}
}
class User {
int id;
String name;
String email;
User({this.id, this.name, this.email});
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json["id"] as int,
name: json["name"] as String,
email: json["email"] as String,
);
}
}
Are you sorting the List ascending/descending? List.sort() can be applied to multidimensional array/List.
This sorts the name in ascending order
filteredUsers = users.sort((a, b) =>
a.name.toLowerCase().compareTo(b.name.toLowerCase()));
For descending, you just need to swap a and b
filteredUsers = users.sort((b, a) =>
a.name.toLowerCase().compareTo(b.name.toLowerCase()));
I've also tested out the filter that you've applied on the List. The filter works without issues. The issue here is that you're adding incompatible type to List<User>. Changing it to List works without issues.
List users = [
{'id': 40, 'name': "moia", 'email': "test#1.com"},
{'id': 40, 'name': "moiaa", 'email': "test#2.com"},
{'id': 40, 'name': "moiab", 'email': "test#3.com"},
];
String keyword = 'moiaa';
filtered = users.where((a) => a['name'].contains(keyword.toLowerCase()) ||
a['email'].toLowerCase().contains(keyword.toLowerCase())).toList();
print(filtered);
The output should print [{id: 40, name: moiaa, email: test#2.com}]
If you'd like to use the User object in the List as List<User>. The List items should be added using the constructor.
List<User> users = [
User(id: 40, name: "moia", email: "test#1.com"),
User(id: 40, name: "moiaa", email: "test#2.com"),
User(id: 40, name: "moiab", email: "test#3.com"),
];
String keyword = 'moiaa';
filtered = users.where((a) => a.name.contains(keyword.toLowerCase()) ||
a.email.toLowerCase().contains(keyword.toLowerCase())).toList();
for(User user in filtered){
print('id: ${user.id} name: ${user.name} email: ${user.email}');
}
The output should print: id: 40 name: moiaa email: test#2.com
Related
I use firestore to save the data. So, I use 'set'method. but It can't save the data. I get the error cannot get a field on a DocumentSnapshotPlatform which does not exist. How can I solve this error?
this my code. first code is input the title and content code. '''
class WritePage extends StatefulWidget {
#override
_WritePageState createState() => _WritePageState();
}
class _WritePageState extends State<WritePage> {
DataBase dataBase = new DataBase();
String title = ' '; //제목
String content = ' '; //내용
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text("글쓰기"),
),
body: Center(
child: ListView(
children: <Widget>[
Column(
children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(20, 20, 20, 5),
child: TextField(
onChanged: (String text) {
if(text != null) {
title = text;
}else{title = 'null';}
},
keyboardType: TextInputType.multiline,
decoration: InputDecoration(
hintText: '제목을 적어주세요',
border: OutlineInputBorder(),
labelText: "제목을 입력하세요.",
),
),
),
Padding(
padding: EdgeInsets.fromLTRB(20, 20, 20, 5),
child: TextField(
onChanged: (String text) {
if(text != null) {
content = text;
}else{content = 'null';}
},
keyboardType: TextInputType.multiline,
maxLines: 20,
decoration: InputDecoration(
hintText: '내용을 적어주세요',
border: OutlineInputBorder(),
labelText: "내용을 입력하세요.",
),
),
),
Padding(
padding: EdgeInsets.fromLTRB(20, 5, 20, 5),
child: SizedBox(
height: 50,
width: 400,
child: TextButton(
onPressed: () async {
DataBase dataBase = new DataBase();
var now = DateTime.now();
await dataBase.add(title, content, '$now');
Navigator.pop(context);
},
child: Text(
'글쓰기',
style: TextStyle(color: Colors.black),
),
style: TextButton.styleFrom(primary: Colors.blue),
),
),
),
],
)
],
),
),
);
}
}
''''
this is my code2. this code is to save the data in firestore.
but it does not work.
class DataBase {
FirebaseFirestore firestore = FirebaseFirestore.instance;
String collection = '게시판';
add(String title, String content, String date_time) {
firestore
.collection('카운트')
.doc('카운트')
.get().then((DocumentSnapshot ds) {
firestore.collection(collection).doc('${ds['카운트']!}').set(
{'제목': title, '내용': content,
'날짜': date_time, 'id': ds['카운트']!});
int id = ds['카운트']! + 1;
cntupdate(id);
});
}
void cntupdate(int _id) {
firestore.collection('카운트').doc('카운트').update({'id': _id,
'카운트': _id});
}
I am putting up 3 .dart files which are required for the app.
StaffEvent.dart
import 'package:flutter/material.dart';
import 'package:flutter_new_app/addevent_screen.dart';
import 'package:flutter_new_app/services/crud.dart';
class StaffEvent extends StatefulWidget {
#override
_StaffEventState createState() => _StaffEventState();
}
class _StaffEventState extends State<StaffEvent> {
CrudMethods crudMethods = new CrudMethods();
QuerySnapshot eventSnapshot;
Stream eventStream;
// ignore: non_constant_identifier_names
Widget EventList() {
return Container(
child: eventStream != null
? Column(
children: [
StreamBuilder(
stream: eventStream,
builder: (context, snapshot) {
return ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 16),
itemCount: eventSnapshot.docs.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return EventTile(
title: eventSnapshot.docs[index].data()['title'],
desc: eventSnapshot.docs[index].data()['desc'],
date: eventSnapshot.docs[index].data()['date'],
);
},
);
},
),
],
)
: Container(
alignment: Alignment.center,
child: CircularProgressIndicator(),
),
);
}
#override
void initState() {
setState(() {
Stream result;
eventStream = result;
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFFffffff),
appBar: AppBar(
actions: [
FloatingActionButton(
backgroundColor: Colors.green,
child: Icon(Icons.add),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => AddEvent()),
);
},
)
],
backgroundColor: Color(0xFFebd8b7),
title: Text(
'Events',
style: TextStyle(color: Colors.black),
),
),
);
}
}
// ignore: must_be_immutable
class EventTile extends StatelessWidget {
String title, desc, date;
EventTile({#required this.title, #required this.desc, #required this.date});
#override
Widget build(BuildContext context) {
return Column(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(6),
child: SizedBox(
width: 500,
height: 80,
child: Container(
color: Color(0xFFeaffd0),
child: Column(
children: [
Text(
title,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 25, fontWeight: FontWeight.w500),
),
Text(
desc,
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w400),
),
Text(
date,
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w400),
)
],
),
),
),
),
],
);
}
}
Crud.dart
import 'package:cloud_firestore/cloud_firestore.dart';
class CrudMethods {
Future<void> addData(eventData) async {
FirebaseFirestore.instance
.collection("events")
.add(eventData)
.catchError((e) {
print(e);
});
}
getData() async {
return await FirebaseFirestore.instance.collection("events").get();
}
}
Addevent.dart
import 'package:flutter_new_app/services/crud.dart';
class AddEvent extends StatefulWidget {
#override
_AddEventState createState() => _AddEventState();
}
class _AddEventState extends State<AddEvent> {
String title, desc, date;
CrudMethods crudMethods = new CrudMethods();
uploadEvent() async {
Map<String, String> eventMap = {"title": title, "desc": desc, "date": date};
crudMethods.addData(eventMap).then((result) {
Navigator.pop(context);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFFffffff),
appBar: AppBar(
backgroundColor: Color(0xFFf38181),
title: Text(
'Add Event',
style: TextStyle(color: Colors.black),
),
actions: <Widget>[
GestureDetector(
onTap: () {
uploadEvent();
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Icon(Icons.file_upload)),
)
],
),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
decoration: InputDecoration(hintText: "Event Name"),
onChanged: (val) {
title = val;
},
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
decoration: InputDecoration(hintText: "Description"),
onChanged: (val) {
desc = val;
},
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
decoration: InputDecoration(hintText: "Date"),
onChanged: (val) {
date = val;
},
),
)
],
));
}
}
So here basically, the user has to enter some details for an event and when clicking the upload button it should be visible as a list in the Staffevent page . That is the problem. Nothung is showing in the Staffevent page. It is blank.
The data is being stored in the firebase database but when i am using snapshot and calling it back it is not showing in my flutter application.
Your stream is empty:
Stream result;
eventStream = result;
Firebase Firestore get() method returns a Future<DocumentSnapshot>:
Future<DocumentSnapshot> getData() async {
return await FirebaseFirestore.instance.collection("events").get();
}
If you need a stream you use snapshots() method which returns a Stream:
Stream collectionStream = FirebaseFirestore.instance.collection("events").snapshots();
Please refer to official documentation to get familiar with Firebase API.
I have an array that looks like this
final thisCategory = [
{
'category': 'Social Life',
'data': [
{'amount': 2000, 'content': 'thanks', 'date': DateTime.now()}
]
},
{
'category': 'Food',
'data': [
{'amount': 2000, 'content': 'thanks','date': DateTime.now()},
{'amount': 2000, 'content': 'thanks','date': DateTime.now()}
]
}
];
and this is how my app looks
my widget look like this
Expanded(
child: Container(
child: ListView.builder(
itemBuilder: (context, index) => TransactitonTile(
category: thisCategory[index]['category'],
amount: amountCategory[index]['amount'].toString(),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Scaffold(
body: SafeArea(
child: Column(
children: [
Text(thisCategory[index]['category']),
Expanded(
child: Container(
child: ListView.builder(
itemBuilder: (context, index) =>
ListTile(
leading: //this is where i want to show 'date' element,
trailing: //this is where i want to show 'amount' element,
title: //this is where i want to show 'content' element,
),
),
),
)
],
),
),
),
),
);
},
),
itemCount: thisCategory.length,
),
),
)
so when the user presses on one of the 'category' like I showed above, then the user will go to the next page which will display what 'content' is in that 'category'. I've tried to display the 'content', but all the 'content' from all the 'category' also appear in the next page. how to fix this?
From the above sample that you provided i have created a example for you:
Following is the smaple json file that you provided
[
{
"category":"Social Life",
"data":[
{
"amount":2000,
"content":"thanks",
"date":"DateTime.now()"
}
]
},
{
"category":"Food",
"data":[
{
"amount":2000,
"content":"thanks",
"date":"DateTime.now()"
},
{
"amount":2000,
"content":"thanks",
"date":"DateTime.now()"
}
]
}
]
And this is the main ui and below is the model class for that.
import 'package:flutter/material.dart';
import 'dart:convert';
// To parse this JSON data, do
//
// final category = categoryFromJson(jsonString);
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Users'),
);
}
}
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<Category> categoryList = List();
bool _isLoading = false;
_getUsers() async {
setState(() {
_isLoading = true;
});
var data =
await DefaultAssetBundle.of(context).loadString("assets/test.json");
categoryList = categoryFromJson(data);
setState(() {
_isLoading = false;
});
}
#override
void initState() {
super.initState();
_getUsers();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: Container(
child: ListView.builder(
itemCount: categoryList.length,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailPage(
category: categoryList[index],
)),
);
},
child: Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(categoryList[index].category),
),
),
);
},
),
),
);
}
}
class DetailPage extends StatefulWidget {
final Category category;
DetailPage({this.category});
#override
_DetailPageState createState() => _DetailPageState();
}
class _DetailPageState extends State<DetailPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: ListView.builder(
itemCount: widget.category.data.length,
itemBuilder: (BuildContext context, int index) {
return Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
Text(widget.category.data[index].amount.toString()),
Text(widget.category.data[index].content),
Text(widget.category.data[index].date),
],
),
));
},
),
),
);
}
}
List<Category> categoryFromJson(String str) =>
List<Category>.from(json.decode(str).map((x) => Category.fromJson(x)));
String categoryToJson(List<Category> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Category {
Category({
this.category,
this.data,
});
String category;
List<Datum> data;
factory Category.fromJson(Map<String, dynamic> json) => Category(
category: json["category"],
data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"category": category,
"data": List<dynamic>.from(data.map((x) => x.toJson())),
};
}
class Datum {
Datum({
this.amount,
this.content,
this.date,
});
int amount;
String content;
String date;
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
amount: json["amount"],
content: json["content"],
date: json["date"],
);
Map<String, dynamic> toJson() => {
"amount": amount,
"content": content,
"date": date,
};
}
Just let me know if it work.
I am trying to add some city list to a dialog with checkbox so that i need to implement multiple click on items. what I am trying to do is given below.
onPressed from button calls Rest Service and on success result I just show a dialog
void showCityDialog(BuildContext context) {
SimpleDialog dialog = new SimpleDialog(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Text(
"CITIES",
style: TextStyle(fontSize: 18.0, color: Colors.black),
textAlign: TextAlign.center,
),
new RaisedButton(
onPressed: () {print("clicked");},
color: Color(0xFFfab82b),
child: new Text(
"Done",
style: TextStyle(color: Colors.white),
),)],),
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Container(
constraints: BoxConstraints(maxHeight: 500.0),
child: ListView.builder(
scrollDirection: Axis.vertical,
itemCount: cityData.length,
itemBuilder: (context, position) {
return new CheckboxListTile(
value: checkboxValueCity,
onChanged: (bool value) {
setState(() {
checkboxValueCity = value;
});
},
activeColor: Color(0xFFfab82b),
dense: true,
title: Text(
cityData[position].city_name,
style: TextStyle(fontSize: 16.0, color: Colors.black),
),);},),),],)],);
showDialog(
context: context,
builder: (BuildContext context) {
return dialog;
});
}
checkboxValueCity is a boolean variable in class , on click of chekboxListItem i need to update checkbox value as checked and uncheced. At the same time need to add/remove that item to a list which is also inside that class.
But in my code checkbox is not refershing on every click but when i close that box and open it again checkbox is checked. then how can i get multiple click from tile and how can i return list from dialog?
Your dialog needs to be a StatefulWidget (Flutter Github issue). The member variable that tracks selection state needs to be in the dialog class. You can use a callback to update a member variable in your parent class with the List of selected cities. There also seem to be some issues using a ListView.builder inside of a SimpleDialog or AlertDialog (search the Flutter Github for issues) so I used a plain Dialog.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Checkbox Dialog Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Checkbox Dialog Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool checkboxValueCity = false;
List<String> allCities = ['Alpha', 'Beta', 'Gamma'];
List<String> selectedCities = [];
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
showDialog(
context: context,
builder: (context) {
return _MyDialog(
cities: allCities,
selectedCities: selectedCities,
onSelectedCitiesListChanged: (cities) {
selectedCities = cities;
print(selectedCities);
});
});
}),
);
}
}
class _MyDialog extends StatefulWidget {
_MyDialog({
this.cities,
this.selectedCities,
this.onSelectedCitiesListChanged,
});
final List<String> cities;
final List<String> selectedCities;
final ValueChanged<List<String>> onSelectedCitiesListChanged;
#override
_MyDialogState createState() => _MyDialogState();
}
class _MyDialogState extends State<_MyDialog> {
List<String> _tempSelectedCities = [];
#override
void initState() {
_tempSelectedCities = widget.selectedCities;
super.initState();
}
#override
Widget build(BuildContext context) {
return Dialog(
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'CITIES',
style: TextStyle(fontSize: 18.0, color: Colors.black),
textAlign: TextAlign.center,
),
RaisedButton(
onPressed: () {
Navigator.pop(context);
},
color: Color(0xFFfab82b),
child: Text(
'Done',
style: TextStyle(color: Colors.white),
),
),
],
),
Expanded(
child: ListView.builder(
itemCount: widget.cities.length,
itemBuilder: (BuildContext context, int index) {
final cityName = widget.cities[index];
return Container(
child: CheckboxListTile(
title: Text(cityName),
value: _tempSelectedCities.contains(cityName),
onChanged: (bool value) {
if (value) {
if (!_tempSelectedCities.contains(cityName)) {
setState(() {
_tempSelectedCities.add(cityName);
});
}
} else {
if (_tempSelectedCities.contains(cityName)) {
setState(() {
_tempSelectedCities.removeWhere(
(String city) => city == cityName);
});
}
}
widget
.onSelectedCitiesListChanged(_tempSelectedCities);
}),
);
}),
),
],
),
);
}
}
Use StatefulBuilder to update Widgets only inside Dialog. StatefulBuilder is best for update sebsection of the widget tree where
state is needed.
simple code snippet
void _showDialog() {
showDialog(
context: context,
builder: (context) {
return StatefulBuilder( // StatefulBuilder
builder: (context, setState) {
return AlertDialog(
actions: <Widget>[
Container(
width: 400,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
"Student Attendence",
style: TextStyle(fontSize: 20),
),
SizedBox(
height: 5,
),
Container(
height: 2,
color: Colors.black,
),
SizedBox(
height: 15,
),
CheckboxListTile(
value: user1,
title: Text("user1"),
onChanged: (value){
setState(() {
user1=value;
});
},
),
Divider(
height: 10,
),
CheckboxListTile(
value: user2,
title: Text("user2"),
onChanged: (value){
setState(() {
user2=value;
});
},
),
Divider(
height: 10,
),
CheckboxListTile(
value: user3,
title: Text("user3"),
onChanged: (value){
setState(() {
user3=value;
});
},
),
Divider(
height: 10,
),
CheckboxListTile(
value: user4,
title: Text("user4"),
onChanged: (value){
setState(() {
user4=value;
});
},
),
Divider(
height: 10,
),
SizedBox(
height: 5,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Material(
elevation: 5.0,
color: Colors.blue[900],
child: MaterialButton(
padding: EdgeInsets.fromLTRB(
10.0, 5.0, 10.0, 5.0),
onPressed: () {},
child: Text("Save",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 15,
)),
),
),
Material(
elevation: 5.0,
color: Colors.blue[900],
child: MaterialButton(
padding: EdgeInsets.fromLTRB(
10.0, 5.0, 10.0, 5.0),
onPressed: () {
setState(() {
Navigator.of(context).pop();
});
},
child: Text("Cancel",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 15,
)),
),
),
Material(
elevation: 5.0,
color: Colors.blue[900],
child: MaterialButton(
padding: EdgeInsets.fromLTRB(
10.0, 5.0, 10.0, 5.0),
onPressed: () {},
child: Text("Select All",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 15,
)),
),
),
],
)
],
))
],
);
},
);
},
);
}
example
Although Albert's answer works, you need not go thru all that. Simply wrap the content: with a StatefulBuilder, voila!
https://api.flutter.dev/flutter/widgets/StatefulBuilder-class.html.
Note: It is important where you declare the variable(s) you want to change.
I modified your code a bit, I want when users check the list, the list won't be updated to the main view, but they will when users click the "Update" button.
But some how, it doesn't work. Can you please check ?
Thank you very much
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Checkbox Dialog Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Checkbox Dialog Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool checkboxValueCity = false;
List<String> allCities = ['Alpha', 'Beta', 'Gamma'];
List<String> selectedCities = [];
List<String> selectedCitiesTemp = [];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("App Bar"),
),
body: Center(
child: Column(
children: <Widget>[
_list(),
RaisedButton(
child: Text("Update From TMP List"),
onPressed: () {
setState(() {
selectedCities = selectedCitiesTemp;
});
},
)
],
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return _MyDialog(
cities: allCities,
selectedCities: selectedCities,
onSelectedCitiesListChanged: (cities) {
setState(() {
selectedCitiesTemp = cities;
});
},
);
});
}),
);
}
Widget _list() {
List<Widget> list = [];
for(String item in selectedCities) {
list.add(ListTile(
title: Text(item),
));
}
return Column(
children: list
);
}
}
class _MyDialog extends StatefulWidget {
_MyDialog({
this.cities,
this.selectedCities,
this.onSelectedCitiesListChanged,
});
final List<String> cities;
final List<String> selectedCities;
final ValueChanged<List<String>> onSelectedCitiesListChanged;
#override
_MyDialogState createState() => _MyDialogState();
}
class _MyDialogState extends State<_MyDialog> {
List<String> _tempSelectedCities = [];
#override
void initState() {
_tempSelectedCities = widget.selectedCities;
super.initState();
}
#override
Widget build(BuildContext context) {
return Dialog(
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'CITIES',
style: TextStyle(fontSize: 18.0, color: Colors.black),
textAlign: TextAlign.center,
),
],
),
Expanded(
child: ListView.builder(
itemCount: widget.cities.length,
itemBuilder: (BuildContext context, int index) {
final cityName = widget.cities[index];
return Container(
child: CheckboxListTile(
title: Text(cityName),
value: _tempSelectedCities.contains(cityName),
onChanged: (bool value) {
if (value) {
if (!_tempSelectedCities.contains(cityName)) {
setState(() {
_tempSelectedCities.add(cityName);
});
}
} else {
if (_tempSelectedCities.contains(cityName)) {
setState(() {
_tempSelectedCities.removeWhere(
(String city) => city == cityName);
});
}
}
widget.onSelectedCitiesListChanged(_tempSelectedCities);
}),
);
}),
),
],
),
);
}
}
my qustion as about flutter and sqflite.
i want to get all items from sqflite and show to the listview.builder.
in part two i want to taped on item of listview and navigate to another page with one parameter, and in new page generate a new listview.builder with new items.
homepage :
body: Center(
child: ListView.builder(
itemCount: _categories.length,
itemBuilder: (_, index) {
return Directionality(
textDirection: TextDirection.rtl,
child: Column(
children: <Widget>[
ListTile(
title: Text(
"${Category.map(_categories[index]).name}",
style: TextStyle(
fontSize: 25.0,
color: Colors.deepOrangeAccent,
),
),
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => FoodListPage(
id: Category.map(_categories[index]).id,
catName:
Category.map(_categories[index]).name)));
},
),
Divider(
height: 5.0,
),
],
),
);
},
),
),
second page:
List foods = [];
void fillFoodsList(int id) async {
var db = new DatabaseHelper();
foods = await db.getAllFoods(id);
print('////////////////////////');
foods.forEach((category) => print(category['ImageName']));
print(foods.length);
}
class FoodListPage extends StatefulWidget {
//get 'id' from home page stateLess
final int id;
final String catName;
FoodListPage({this.id, this.catName});
//end
#override
State<StatefulWidget> createState() {
return new _FoodListPageState();
}
}
class _FoodListPageState extends State<FoodListPage> {
#override
void initState() {
// TODO: implement initState
super.initState();
setState(() {
fillFoodsList(widget.id); // call and fill foods
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('لیست خوراکی ها' + "${widget.catName}"),
),
// body: Center(child: Text(foods.length.toString()),),
body: Center(
child: ListView.builder(
itemCount: foods.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(
"${Food.map(foods[index]).name}"
// "vvvvvvvvvvvv"
,
style: TextStyle(
fontSize: 25.0,
color: Colors.deepOrangeAccent,
),
),
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => FoodSinglePage(
id: Food.map(foods[index]).id,
mezaj: Food.map(foods[index]).mezaj,
name: Food.map(foods[index]).name,
value: Food.map(foods[index]).value,
description: Food.map(foods[index]).description,
image: Food.map(foods[index]).image,
favorite: Food.map(foods[index]).favotite,
)));
},
);
},
),
),
);
}
}
with this codes i found solution but listview in second page is cached data from
previous request!