Show of array on another site - arrays

So im trying to create a training app where i can type excercise, sets, reps and load and give it a specific time. I have done this with a calender widget. My page where i have createt the Editingpage looks like this
class EventEditingPage extends StatefulWidget {
final Event? event;
const EventEditingPage({Key? key, this.event}) : super(key: key);
#override
_EventEditingPageState createState() => _EventEditingPageState();
}
class _EventEditingPageState extends State<EventEditingPage> {
final _formKey = GlobalKey<FormState>();
final titleController = TextEditingController();
final List<TextEditingController> setsController = [];
final List<TextEditingController> repsController = [];
final List<TextEditingController> loadController = [];
List<String> exceriseItems = ['Squat', 'Deadlift', 'Bench'];
List<String> selectedExercise = [];
int numberOfTextFields = 1;
late DropdownButton Exercise;
late DateTime fromDate;
late DateTime toDate;
#override
void initState() {
super.initState();
createControllers();
if (widget.event == null) {
fromDate = DateTime.now();
toDate = DateTime.now().add(Duration(hours: 1, minutes: 30));
} else {
final event = widget.event!;
titleController.text = event.title;
createControllers();
selectedExercise[0] =
event.Exercise != "" ? event.Exercise : exceriseItems[0];
setsController[0].text = event.Sets;
repsController[0].text = event.Reps;
loadController[0].text = event.Load;
fromDate = event.from;
toDate = event.to;
}
}
#override
void dispose() {
titleController.dispose();
setsController.forEach((TextEditingController element) {
element.dispose();
});
repsController.forEach((TextEditingController element) {
element.dispose();
});
loadController.forEach((TextEditingController element) {
element.dispose();
});
super.dispose();
}
List<TextEditingController> _textEditingControllers = [
TextEditingController()
];
#override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
leading: CloseButton(),
actions: buildEditingActions(),
backgroundColor: Colors.red,
),
body: SingleChildScrollView(
padding: EdgeInsets.all(12),
child: Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text("Trænings Information", style: TextStyle(fontSize: 24)),
buildTitle(),
SizedBox(height: 12),
buildDateTimePickers(),
Text("\nTræningen", style: TextStyle(fontSize: 24)),
for (int i = 0; i < numberOfTextFields; i++)
buildExerciseComplete(i),
buildAddMore(),
],
),
),
),
);
List<Widget> buildEditingActions() => [
ElevatedButton.icon(
style: ElevatedButton.styleFrom(
primary: Colors.transparent, shadowColor: Colors.transparent),
onPressed: saveForm,
icon: Icon(Icons.done),
label: Text('Save'),
)
];
createControllers() {
for (var i = 0; i < numberOfTextFields; i++) {
setsController.add(TextEditingController());
repsController.add(TextEditingController());
loadController.add(TextEditingController());
}
selectedExercise.add(exceriseItems[0]);
}
Widget buildTitle() => TextFormField(
style: TextStyle(fontSize: 24),
decoration: InputDecoration(
border: UnderlineInputBorder(),
hintText: 'Add Title',
),
onFieldSubmitted: (_) => saveForm,
validator: (title) =>
title != null && title.isEmpty ? 'Title cannot be empty' : null,
controller: titleController,
);
Widget buildExerciseComplete(int idx) => Container(
padding: const EdgeInsets.all(5.0),
decoration: BoxDecoration(
color: const Color.fromARGB(255, 255, 200, 200),
borderRadius: BorderRadius.circular(5.0),
border: Border.all(
width: 2.0,
),
),
height: 50,
child: Row(
children: <Widget>[
Expanded(
child: Row(
children: <Widget>[
Expanded(child: buildExercise(idx)),
Expanded(child: buildSets(idx)),
Expanded(child: buildReps(idx)),
Expanded(child: buildLoad(idx)),
],
),
),
],
),
);
Widget buildSets(int idx) => TextFormField(
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly
],
style: const TextStyle(fontSize: 15),
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Sets',
),
onFieldSubmitted: (_) => saveForm,
validator: (sets) =>
sets != null && sets.isEmpty ? 'Sets cannot be empty' : null,
controller: setsController[idx],
);
Widget buildReps(int idx) => TextFormField(
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly
],
style: const TextStyle(fontSize: 15),
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Reps',
),
onFieldSubmitted: (_) => saveForm,
validator: (reps) =>
reps != null && reps.isEmpty ? 'Reps cannot be empty' : null,
controller: repsController[idx],
);
Widget buildLoad(int idx) => TextFormField(
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly
],
style: const TextStyle(fontSize: 15),
decoration: const InputDecoration(
labelText: 'Load',
border: const OutlineInputBorder(),
),
onFieldSubmitted: (_) => saveForm,
validator: (load) =>
load != null && load.isEmpty ? 'Load cannot be empty' : null,
controller: loadController[idx],
);
Widget buildExercise(int idx) => DropdownButton<String>(
value: selectedExercise[idx],
icon: const Icon(Icons.arrow_drop_down),
elevation: 16,
style: const TextStyle(color: Colors.black),
onChanged: (String? newValue) {
setState(() {
selectedExercise[idx] = newValue!;
});
},
items: exceriseItems.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
Widget buildDateTimePickers() => Column(
children: [
buildFrom(),
buildTo(),
],
);
Widget buildFrom() => buildHeader(
header: 'FROM',
child: Row(
children: [
Expanded(
flex: 2,
child: buildDropdownField(
text: Utils.toDate(fromDate),
onClicked: () => pickFromDateTime(pickDate: true),
),
),
Expanded(
child: buildDropdownField(
text: Utils.toTime(fromDate),
onClicked: () => pickFromDateTime(pickDate: false),
),
),
],
),
);
Widget buildTo() => buildHeader(
header: 'TO',
child: Row(
children: [
Expanded(
flex: 2,
child: buildDropdownField(
text: Utils.toDate(toDate),
onClicked: () => pickToDateTime(pickDate: true),
),
),
Expanded(
child: buildDropdownField(
text: Utils.toTime(toDate),
onClicked: () => pickToDateTime(pickDate: false),
),
),
],
),
);
Widget buildDropdownField({
required String text,
required VoidCallback onClicked,
}) =>
ListTile(
title: Text(text),
trailing: Icon(Icons.arrow_drop_down),
onTap: onClicked,
);
Widget buildHeader({
required String header,
required Widget child,
}) =>
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
header,
style: TextStyle(fontWeight: FontWeight.bold),
),
child,
],
);
Widget buildAddMore() => ElevatedButton(
onPressed: () {
setState(() {
numberOfTextFields++;
createControllers();
});
},
child: const Text('Add new exercise'),
);
Future pickFromDateTime({required bool pickDate}) async {
final date = await pickDateTime(fromDate, pickDate: pickDate);
if (date == null) return;
if (date.isAfter(toDate)) {
toDate =
DateTime(date.year, date.month, date.day, toDate.hour, toDate.minute);
}
setState(() => fromDate = date);
}
Future pickToDateTime({required bool pickDate}) async {
final date = await pickDateTime(
toDate,
pickDate: pickDate,
firstDate: pickDate ? fromDate : null,
);
if (date == null) return;
setState(() => toDate = date);
}
Future<DateTime?> pickDateTime(
DateTime initialDate, {
required bool pickDate,
DateTime? firstDate,
}) async {
if (pickDate) {
final date = await showDatePicker(
context: context,
initialDate: initialDate,
firstDate: firstDate ?? DateTime(2020),
lastDate: DateTime(2100),
);
final time =
Duration(hours: initialDate.hour, minutes: initialDate.minute);
if (date == null) return null;
return date.add(time);
} else {
final timeOfDay = await showTimePicker(
context: context,
initialTime: TimeOfDay.fromDateTime(initialDate),
);
if (timeOfDay == null) return null;
final date =
DateTime(initialDate.year, initialDate.month, initialDate.day);
final time = Duration(hours: timeOfDay.hour, minutes: timeOfDay.minute);
return date.add(time);
}
}
Future saveForm() async {
final isValid = _formKey.currentState!.validate();
if (isValid) {
final event = Event(
title: titleController.text,
from: fromDate,
to: toDate,
Exercise: selectedExercise[0],
Sets: setsController[0],
Reps: repsController[0],
Load: loadController[0]);
final isEditing = widget.event != null;
final provider = Provider.of<EventProvider>(context, listen: false);
if (isEditing) {
provider.editEvent(event, widget.event!);
Navigator.of(context).pop();
} else {
provider.addEvent(event);
}
Navigator.of(context).pop();
}
}
}
class Event {
final String title;
final Exercise;
final Sets;
final Reps;
final Load;
final DateTime from;
final DateTime to;
final Color backgroundColor;
final bool isAllDay;
const Event({
required this.title,
required this.Exercise,
required this.Sets,
required this.Reps,
required this.Load,
required this.from,
required this.to,
this.backgroundColor = Colors.lightGreen,
this.isAllDay = false,
});
}
Im now trying to create a Viewing page where you can see you workout you have createt. I was thinking the basics to be like this
class EventViewingPage extends StatelessWidget {
final Event event;
#override
const EventViewingPage({
Key? key,
required this.event,
}) : super(key: key);
#override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(event.title),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.edit,
color: Colors.white,
),
onPressed: () => Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (context) => EventEditingPage(
event: event,
),
),
),
),
IconButton(
icon: Icon(
Icons.delete,
color: Colors.white,
),
onPressed: () {},
)
],
),
body: ListView(
padding: EdgeInsets.all(32),
children: <Widget>[
SizedBox(height: 32),
Text(
"Show the data here",
style: TextStyle(
fontSize: 24,
),
),
],
),
);
}
But im not quite sure on how to display all the information when you add multiple exercises to the training
Hope someone can help, thanks in advance

Related

I want to access the single document from firebase and use it show the data and update it

I was trying to get the single doc data from firebase and wanted to update
'''
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter_neumorphic/flutter_neumorphic.dart';
import 'package:wallet_app/utils/custom_textfield.dart';
import '../module/firebase_data.dart';
import '../utils/utilts.dart';
class EditPage extends StatefulWidget {
const EditPage({
Key? key,
required this.docId,
}) : super(key: key);
final String docId;
#override
State<EditPage> createState() => _EditPageState();
}
class _EditPageState extends State<EditPage> {
late DocumentSnapshot data;
Future getData() async {
User? user = FirebaseAuth.instance.currentUser;
await FirebaseFirestore.instance
.collection('users')
.doc(user?.uid)
.collection('transactions')
.doc(widget.docId)
.get()
.then((value) => data = value);
}
#override
Widget build(BuildContext context) {
TextEditingController titleController =
TextEditingController(text: data['title']);
TextEditingController amountController =
TextEditingController(text: data['amount'].toString());
TextEditingController descriptionController =
TextEditingController(text: data['description']);
bool income = data['type'];
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
foregroundColor: Colors.grey.shade800,
elevation: 0,
centerTitle: true,
title: const Text(
'Edit Transaction',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
body: FutureBuilder(
future: getData(),
builder: (context, snapshot) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CustomTextfield(
hintText: 'Title', controller: titleController),
CustomTextfield(
hintText: 'Amount',
controller: amountController,
keyBoradType: TextInputType.number,
),
CustomTextfield(
hintText: 'Description',
controller: descriptionController,
miniLines: 4,
maxLines: 10),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Expense',
style: TextStyle(
fontWeight: FontWeight.w500, fontSize: 18),
),
Switch(
activeColor: Colors.green.shade300,
inactiveTrackColor: Colors.red.shade300,
inactiveThumbColor: Colors.red.shade100,
value: income,
onChanged: (v) {
setState(() {
income = v;
});
}),
const Text(
'Income',
style: TextStyle(
fontWeight: FontWeight.w500, fontSize: 18),
),
],
),
NeumorphicButton(
margin: const EdgeInsets.only(top: 15),
style: NeumorphicStyle(
shape: NeumorphicShape.flat,
color: Colors.grey.shade800,
depth: 6,
),
onPressed: () async {
if (titleController.text.isEmpty &&
amountController.text.isEmpty) {
Utils.showError(message: 'Please fill all the fields');
return;
} else {
FireData()
.updateTransaction(
title: titleController.text,
description: descriptionController.text,
amount: double.parse(amountController.text),
type: income,
docId: widget.docId)
.then((value) => {
if (income == true)
{
Utils.showError(
message: 'Income Edited Successfully')
}
else
{
Utils.showError(
message:
'Expense Edited Successfully')
},
titleController.clear(),
descriptionController.clear(),
amountController.clear(),
income = false,
});
Navigator.pop(context);
}
},
child: const Text(
'Edit Transaction',
style: TextStyle(
fontSize: 20,
color: Colors.white,
fontWeight: FontWeight.w500,
),
),
),
TextButton(onPressed: () => data, child: const Text('data'))
],
),
);
}),
);
}
}
'''
I want to update the data note I am using setState function to update the state of the slider but its not updating. I want to show the available data and then allow to update it.
I also tried to get the data from the previous page but I even got stuck in that if.
I can get the Data from previous page if there's any solution for that also we will try that method.

firestore.set does not save the data in firestore. cannot get a field on a DocumentSnapshotPlatform which does not exist

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 not able to retrieve data from firebase database in my flutter app. I don't know what is wrong in my code

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.

Flutter Firebase query array to change button color

Screenshot here
I would like to change the color of my arrow (Icon Button) after querying my firebase (likedby) array. Essentially my upvote / downvote system works by adding the user to a likedby/dislikedby array on the post and I want the arrow color to change if the users id is in the likedby or dislikedby arrays.
class HomeScreen extends StatefulWidget {
final String currentUserId;
const HomeScreen({Key key, this.currentUserId}) : super(key: key);
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(backgroundColor: Color(0xffff5722), title: Text("Feed")),
body: StreamBuilder(
stream: FirebaseFirestore.instance
.collection('The Laryngoscope')
.snapshots(),
builder:
(BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
return ListView(
children: snapshot.data.docs.map((document) {
return Center(
child: Padding(
padding: EdgeInsets.fromLTRB(15, 6, 15, 2),
child: Card(
elevation: 8.0,
child: Column(
children: [
ListTile(
title: Text(document['title'] + "\n"),
subtitle: Text(document['authors']),
),
Divider(),
ButtonBar(
children: [
Text(document['likes'].toString()),
IconButton(
icon: Icon(
FontAwesomeIcons.chevronUp,
color: Colors.grey,
size: 30,
),
onPressed: () async {
articleRef.doc(document['title']).update({
"dislikedby": FieldValue.arrayRemove(
[widget.currentUserId]),
"likedby": FieldValue.arrayUnion(
[widget.currentUserId])
});
var documents = (await articleRef
.doc(document['title'])
.get());
articleRef.doc(document['title']).update({
"likes":
(documents.data()['likedby'].length) -
(documents
.data()['dislikedby']
.length)
});
}),
IconButton(
icon: Icon(
FontAwesomeIcons.chevronDown,
color: Colors.grey,
size: 30,
),
onPressed: () async {
articleRef.doc(document['title']).update({
"likedby": FieldValue.arrayRemove(
[widget.currentUserId]),
"dislikedby": FieldValue.arrayUnion(
[widget.currentUserId])
});
var documents = (await articleRef
.doc(document['title'])
.get());
articleRef.doc(document['title']).update({
"likes": (documents
.data()['likedby']
.length) -
(documents.data()['dislikedby'].length)
});
},
),
OutlinedButton(
style: ElevatedButton.styleFrom(
primary: Colors.white, // background
onPrimary: Color(0xffff5722), // foreground
),
onPressed: () {},
child: Text('Comment'),
),
FloatingActionButton(
child: Icon(Icons.share),
backgroundColor: Color(0xFFFF5722),
onPressed: () {},
),
],
)
],
),
),
),
);
}).toList(),
);
}),
);
}
}

update checkbox and return value from dialog in flutter

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);
}),
);
}),
),
],
),
);
}
}

Resources