add staff id instead of username in flutter - database

I want to add staff id instead of username and staff id save in database how can i do this Please guide me i cannot understand how can i do this. when i selected particular username the staff id not save in database it give error like LateInitializationError: Field 'staff_Id' has already been initialized.
class AppointmentDetailsEditPage extends StatefulWidget {
final int aptId;
//late final int staffid;
final int staff_Id;
final int docID;
final String dTitle;
final int tNo;
final String aptExecutive;
AppointmentDetailsEditPage(
this.aptId,
// this.staffid,
this.staff_Id,
this.docID,
this.dTitle,
this.tNo,
this.aptExecutive);
#override
_AppointmentDetailsEditPageState createState() =>
_AppointmentDetailsEditPageState(
this.aptId,
//this.staffid,
this.staff_Id,
this.docID,
this.dTitle,
this.tNo,
this.aptExecutive);
}
class _AppointmentDetailsEditPageState
extends State<AppointmentDetailsEditPage> {
var paymentMode = ["Online", "Cash", "Cheque"];
String? selectedMode;
var items = ["Owner", "Tenant", "Agent", "Both"];
// late final int dID;
var status = ["Open", "Closed", "Cancel"];
TextStyle style = const TextStyle(fontFamily: 'Montserrat', fontSize: 6.0);
AppointmentController appointmentController =
Get.put(AppointmentController());
late Future<Appointment> futureAppointments;
late final int aptId;
// late final int staffid;
late final int staff_Id;
late final int docID;
late final String dTitle;
late final int tNo;
late String aptExecutive;
List<Appointment> aptmnt = [];
_AppointmentDetailsEditPageState(
this.aptId,
//this.staffid,
this.staff_Id,
this.docID,
this.dTitle,
this.tNo,
this.aptExecutive,
);
#override
void initState() {
super.initState();
futureAppointments =
AppointmentController.fetchAppointmentsById(this.aptId);
init();
}
Future init() async {
print('apt ID $aptId');
final aptmnt = await AppointmentController.fetchAppointments;
setState(() {
this.aptmnt = aptmnt as List<Appointment>;
print(aptmnt);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color.fromARGB(255, 3, 87, 156),
title: Text('Edit Appointment'),
// flexibleSpace: LogOut(),
leading: IconButton(
icon: BackButtonIcon(),
onPressed: () => Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => AppointmentDetails(
aptId, staff_Id, docID, dTitle, tNo, aptExecutive)))),
),
body:
//SafeArea(
Center(
child: SafeArea(
child: SingleChildScrollView(
child: Container(
alignment: Alignment.center,
child: FutureBuilder<Appointment>(
future: futureAppointments,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasData) {
return Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.all(7),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
// height: 80.0,
width:
MediaQuery.of(context).size.width *
0.4,
child: TypeAheadField<UserLogin>(
hideSuggestionsOnKeyboardHide: true,
textFieldConfiguration:
TextFieldConfiguration(
decoration: InputDecoration(
errorStyle: const TextStyle(
fontSize: 0.05),
fillColor: Color.fromARGB(
255, 233, 246, 252),
// prefixIcon: Icon(Icons.search),
suffixIcon: GestureDetector(
child: Icon(
Icons.close,
color: Color.fromARGB(
137, 221, 221, 221),
size: 20,
),
onTap: () {
aptExecutiveController
.clear();
FocusScope.of(context)
.requestFocus(
FocusNode());
},
),
border: OutlineInputBorder(
// borderRadius: BorderRadius.circular(10.0),
),
hintText:
'Appointment Executive ',
labelText:
'Appointment Executive',
hintStyle:
TextStyle(fontSize: 12),
),
controller: this
.aptExecutiveController =
TextEditingController(
text:
'${this.aptExecutive}'),
),
suggestionsCallback: (pattern) async {
return await LoginController
.users();
},
itemBuilder:
(context, UserLogin allUsers) {
final user = allUsers;
return ListTile(
title: Text(user.userName),
);
},
noItemsFoundBuilder: (context) =>
Container(
height: 50,
child: Center(
child: Text(
'No Staff Found.',
style: TextStyle(fontSize: 12),
),
),
),
onSuggestionSelected:
(UserLogin? AllUsers) {
final user = AllUsers!;
this.aptExecutiveController.text =
user.userName;
//this.uId = stID;
setState(() {
this.staff_Id = user.userId;
});
},
),
),
child: ElevatedButton(
onPressed: () {
final int aptId = this.aptId;
print('apt id update $aptId');
final int staffId = this.staff_Id;
print('staff id update $staff_Id');
final int docId = this.docID;
print('doc id update $docID');
Navigator.of(context).push(
MaterialPageRoute(
builder:
(BuildContext context) =>
AppointmentDetails(
aptId,
staff_Id,
docID,
dTitle,
tNo,
aptExecutive)));
setState(() {
futureAppointments =
createAppointment(
aptId,
staffId,
docId,
);
});
},
child: const Text(
"Save",
style: TextStyle(fontSize: 17),
),

Related

Problem with Navigation (Error: Range Error (index): Index out of range: no indicies are valid:0)

When i am update some field then it updated successfully and redirect on detail Page but it give following error to me when redirect: Range Error index out of range:no indices are valid:0. I cannot get what is the problem in my code.Please guide me about it. I am attaching my code here,
AppointmentDetailEditPage
class AppointmentDetailsEditPage extends StatefulWidget {
final int aptId;
final int docID;
final int staffId;
final String dTitle;
final int tNo;
final String aptExecutive;
AppointmentDetailsEditPage(
this.aptId,
this.docID,
this.staffId,
this.dTitle,
this.tNo,
// this.doctitle,
// this.docToken,
this.aptExecutive);
#override
_AppointmentDetailsEditPageState createState() =>
_AppointmentDetailsEditPageState(this.aptId, this.docID, this.staffId,
this.dTitle, this.tNo, this.aptExecutive);
}
class _AppointmentDetailsEditPageState
extends State<AppointmentDetailsEditPage> {
var paymentMode = ["Online", "Cash", "Cheque"];
String? selectedMode;
var items = ["Owner", "Tenant", "Agent", "Both"];
var status = ["Open", "Closed", "Cancel"];
TextStyle style = const TextStyle(fontFamily: 'Montserrat', fontSize: 6.0);
AppointmentController appointmentController =
Get.put(AppointmentController());
late Future<Appointment> futureAppointments;
late final int aptId;
late final int docID;
late final int staffId;
late final String dTitle;
late final int tNo;
final String aptExecutive;
List<Appointment> aptmnt = [];
_AppointmentDetailsEditPageState(
this.aptId,
this.docID,
this.staffId,
this.dTitle,
this.tNo,
this.aptExecutive,
);
#override
void initState() {
super.initState();
futureAppointments =
AppointmentController.fetchAppointmentsById(this.aptId);
init();
}
Future init() async {
print('apt ID $aptId');
final aptmnt = await AppointmentController.fetchAppointments;
setState(() {
this.aptmnt = aptmnt as List<Appointment>;
print(aptmnt);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color.fromARGB(255, 3, 87, 156),
title: Text('Edit Appointment'),
// flexibleSpace: LogOut(),
leading: IconButton(
icon: BackButtonIcon(),
onPressed: () => Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => AppointmentDetails(
aptId, docID, staffId, dTitle, tNo, aptExecutive)))),
),
body:
//SafeArea(
Center(
child: SafeArea(
child: SingleChildScrollView(
child: Container(
alignment: Alignment.center,
child: FutureBuilder<Appointment>(
future: futureAppointments,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasData) {
return Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.all(7),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
// height: 80.0,
width:
MediaQuery.of(context).size.width *
0.4,
child: TypeAheadField<UserLogin>(
hideSuggestionsOnKeyboardHide: true,
textFieldConfiguration:
TextFieldConfiguration(
decoration: InputDecoration(
errorStyle: const TextStyle(
fontSize: 0.05),
fillColor: Color.fromARGB(
255, 233, 246, 252),
// prefixIcon: Icon(Icons.search),
suffixIcon: GestureDetector(
child: Icon(
Icons.close,
color: Color.fromARGB(
137, 221, 221, 221),
size: 20,
),
onTap: () {
aptExecutiveController
.clear();
FocusScope.of(context)
.requestFocus(
FocusNode());
},
),
border: OutlineInputBorder(
// borderRadius: BorderRadius.circular(10.0),
),
hintText:
'Appointment Executive ',
// labelText: 'Appointment Executive',
hintStyle:
TextStyle(fontSize: 12),
),
controller: aptExecutiveController =
TextEditingController(
text:
'${this.aptExecutive}'),
),
suggestionsCallback: (pattern) async {
return await LoginController
.users();
},
itemBuilder:
(context, UserLogin? allUsers) {
final user = allUsers!;
return ListTile(
title: Text(user.userName),
);
},
noItemsFoundBuilder: (context) =>
Container(
height: 50,
child: Center(
child: Text(
'No Staff Found.',
style: TextStyle(fontSize: 12),
),
),
),
onSuggestionSelected:
(UserLogin? AllUsers) {
final user = AllUsers!;
this.aptExecutiveController.text =
user.userName;
setState(() {
this.staffid = user.userId;
// this.staffid = user.userId;
// print('$staffid');
print('$staffid');
// aptExecutive;
});
},
),
),
Navigator.of(context).push(
MaterialPageRoute(
builder:
(BuildContext context) =>
AppointmentDetails(
aptId,
docID,
staffId,
dTitle,
tNo,
aptExecutive)));
AppointmentController
import 'dart:convert';
import 'dart:ui';
import 'package:AtDocHUB/Model/Appointment.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:http/http.dart' as http;
import 'dart:async';
class AppointmentController {
// fetch list of appointment
static FutureOr<Iterable<Appointment>> fetchAppointments(String title) async {
// final url = Uri.parse('http://192.168.0.134:8080/AtdochubJ-3/appointment/');
final url = Uri.parse(
'http://3.108.194.111:8080/AtdochubJ-3/appointment/appointmentdetails'
// 'http://3.108.194.111:8080/AtdochubJ-3/appointment/appointmentdetails'
);
final response = await http.get(url);
if (response.statusCode == 200) {
final List docs = json.decode(response.body);
return docs.map((json) => Appointment.fromJson(json)).where((doc) {
final titleLower = doc.docTitle.toLowerCase();
final tokenLower = doc.tokenNo.toString();
final searchLower = title.toLowerCase();
return titleLower.contains(searchLower) ||
tokenLower.contains(searchLower);
}).toList();
} else {
throw Exception();
}
}
//list of appointment
static Future<List<Appointment>> fetchAppointmentList() async {
final response = await http.get(Uri.parse(
'http://3.108.194.111:8080/AtdochubJ-3/appointment/appointmentdetails'));
//print(fromJson(json)).toList());
if (response.statusCode == 200) {
final parsed = json.decode(response.body).cast<Map<String, dynamic>>();
return parsed
.map<Appointment>((json) => Appointment.fromJson(json))
.toList();
//return Document.fromJson(jsonDecode(response.body));
} else {
throw Exception('Failed to load Appointment');
}
}
//fetch list of appointment by id
static Future<Appointment> fetchAppointmentsById(aptId) async {
final response = await http.get(
Uri.parse(
'http://3.108.194.111:8080/AtdochubJ-3/appointment/find/${aptId}'),
);
if (response.statusCode == 200) {
return Appointment.fromJson(jsonDecode(response.body)[0]);
} else {
throw Exception('Failed to load Appointment');
}
}
Future<Appointment> createAppointment(
int? aptId,
int? docId,
int staffId,
//String docTitle,
// String tokenNo,
String partyName,
String contactNo,
String partyType,
String aptPlace,
String city,
int? feesCollected,
int totalFees,
String paymentMode,
String aptDate,
String aptTime,
// String aptExecutive,
String aptStatus,
String comments,
// String createdAt,
) async {
final response = await http.put(
// Uri.parse('http://192.168.0.134:8080/AtdochubJ-3/appointment/register'),
Uri.parse('http://3.108.194.111:8080/AtdochubJ-3/appointment/register'
// 'http://3.108.194.111:8080/AtdochubJ-3/appointment/register'
),
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, dynamic>{
'aptId': aptId,
'docId': docId,
'staffId': staffId,
'partyName': partyName,
'contactNo': contactNo,
'partyType': partyType,
'aptPlace': aptPlace,
'city': city,
'feesCollected': feesCollected!,
'totalFees': totalFees,
'paymentMode': paymentMode,
'aptDate': aptDate,
'aptTime': aptTime,
//'aptExecutive': aptExecutive,
'aptStatus': aptStatus,
'comments': comments,
// 'createdAt': createdAt,
}));
if (response.statusCode == 200 || response.statusCode == 201) {
return Appointment.fromJson(jsonDecode(response.body)[0]);
else{
throw Exception(' Failed To Create Appointment');
}
AppointmentDetailPage
class AppointmentDetails extends StatefulWidget {
final int aptId;
final int staff_Id;
late final int docID;
final String dTitle;
final int tNo;
final String aptExecutive;
// final String doctitle;
// final String docToken;
AppointmentDetails(this.aptId, this.staff_Id, this.docID, this.dTitle,
this.tNo, this.aptExecutive);
#override
_AppointmentDetailsState createState() => _AppointmentDetailsState(
this.aptId,
this.staff_Id,
this.docID,
this.dTitle,
this.tNo,
this.aptExecutive,
);
}
class _AppointmentDetailsState extends State<AppointmentDetails> {
AppointmentController appointmentController =
Get.put(AppointmentController());
late Future<Appointment> futureAppointments;
final int aptId;
final int staff_Id;
final int docID;
final String dTitle;
final int tNo;
final String aptExecutive;
_AppointmentDetailsState(this.aptId, this.staff_Id, this.docID, this.dTitle,
this.tNo, this.aptExecutive);
#override
void initState() {
super.initState();
// print('detail staff ID $staff_Id');
// print('detail doc ID $docId');
print('apt detail...... $aptId, $dTitle, $tNo, $aptExecutive');
futureAppointments =
AppointmentController.fetchAppointmentsById(this.aptId);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color.fromARGB(255, 3, 87, 156),
title: Text('Appointment Details'),
leading: IconButton(
icon: BackButtonIcon(),
onPressed: () => Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => AppointmentPageFE()))),
),
body: Center(
child: FutureBuilder<Appointment>(
future: futureAppointments,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView(children: [
SafeArea(
child: SingleChildScrollView(
child: Container(
padding: EdgeInsets.all(15),
height: 750,
child: SelectionArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Document Title: ' + this.dTitle,
style: const TextStyle(fontSize: 15.0)),
Text('Token No :' + this.tNo.toString(),
style: const TextStyle(fontSize: 15.0)),
Text("Party Name : " + snapshot.data!.partyName,
style: const TextStyle(fontSize: 15.0)),
Text(
'Appointment Executive :' + this.aptExecutive,
style: const TextStyle(fontSize: 15.0)),
Text("Contact No : " + snapshot.data!.contactNo,
style: const TextStyle(fontSize: 15.0)),
Text("Party Type : " + snapshot.data!.partyType,
style: const TextStyle(fontSize: 15.0)),
Text(
"Appointment Place : " +
snapshot.data!.aptPlace,
style: const TextStyle(fontSize: 15.0)),
Text("Appointment City : " + snapshot.data!.city,
style: const TextStyle(fontSize: 15.0)),
Text(
"Appointment Date : " +
snapshot.data!.aptDate,
style: const TextStyle(fontSize: 15.0)),
Text(
"Appointment Time : " +
snapshot.data!.aptTime,
style: const TextStyle(fontSize: 15.0)),
Text(
"Appointment Status : " +
snapshot.data!.aptStatus,
style: const TextStyle(fontSize: 15.0)),
Text(
"Fees : " +
snapshot.data!.totalFees.toString(),
style: const TextStyle(fontSize: 15.0)),
Text(
"Fees Collected : " +
snapshot.data!.feesCollected.toString(),
style: const TextStyle(fontSize: 15.0)),
Text(
"Payment Mode : " +
snapshot.data!.paymentMode,
style: const TextStyle(fontSize: 15.0)),
Text("Comments : " + snapshot.data!.comments,
style: const TextStyle(fontSize: 15.0)),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
alignment: Alignment.center,
height: 35,
width: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Color.fromARGB(255, 3, 89, 168),
),
child: TextButton(
// style:
// TextButton.styleFrom(fixedSize: Size.fromHeight(300)),
child: const Text(
'Edit ',
style: TextStyle(
fontSize: 17.0,
fontWeight: FontWeight.bold,
color: Colors.white,
backgroundColor:
Color.fromARGB(255, 3, 89, 168),
),
),
onPressed: () {
print(
'apt executive.......${aptExecutive}');
Navigator.of(context)
.pushAndRemoveUntil(
MaterialPageRoute(
builder: (BuildContext
context) =>
AppointmentDetailsEditPage(
this.aptId,
this.staff_Id,
this.docID,
this.dTitle,
this.tNo,
this.aptExecutive,
)),
(Route<dynamic> route) =>
false);
},
),
),
],
),
]),
),
),
// ),
padding: const EdgeInsets.all(10),
),
),
]);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
// By default, show a loading spinner.
return const CircularProgressIndicator();
},
),
),
);
}
}

Problem with Navigation (Error: Range Error (index): Index out of range: no indicies are valid:0) when i navigate edit page to detailPage give error

When i am update some field then it updated successfully and redirect on detail Page but it give following error to me when redirect:
RangeError index out of range:no indices are valid:0.
I cannot get what is the problem in my code.Please guide me about it.
I am attaching my code here
AppointmentDetailEditPage
class AppointmentDetailsEditPage extends StatefulWidget {
final int aptId;
final int docID;
final int staffId;
final String dTitle;
final int tNo;
final String aptExecutive;
AppointmentDetailsEditPage(
this.aptId,
this.docID,
this.staffId,
this.dTitle,
this.tNo,
// this.doctitle,
// this.docToken,
this.aptExecutive);
#override
_AppointmentDetailsEditPageState createState() =>
_AppointmentDetailsEditPageState(this.aptId, this.docID, this.staffId,
this.dTitle, this.tNo, this.aptExecutive);
}
class _AppointmentDetailsEditPageState
extends State<AppointmentDetailsEditPage> {
var paymentMode = ["Online", "Cash", "Cheque"];
String? selectedMode;
var items = ["Owner", "Tenant", "Agent", "Both"];
var status = ["Open", "Closed", "Cancel"];
TextStyle style = const TextStyle(fontFamily: 'Montserrat', fontSize: 6.0);
AppointmentController appointmentController =
Get.put(AppointmentController());
late Future<Appointment> futureAppointments;
late final int aptId;
late final int docID;
late final int staffId;
late final String dTitle;
late final int tNo;
final String aptExecutive;
List<Appointment> aptmnt = [];
_AppointmentDetailsEditPageState(
this.aptId,
this.docID,
this.staffId,
this.dTitle,
this.tNo,
this.aptExecutive,
);
#override
void initState() {
super.initState();
futureAppointments =
AppointmentController.fetchAppointmentsById(this.aptId);
init();
}
Future init() async {
print('apt ID $aptId');
final aptmnt = await AppointmentController.fetchAppointments;
setState(() {
this.aptmnt = aptmnt as List<Appointment>;
print(aptmnt);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color.fromARGB(255, 3, 87, 156),
title: Text('Edit Appointment'),
// flexibleSpace: LogOut(),
leading: IconButton(
icon: BackButtonIcon(),
onPressed: () => Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => AppointmentDetails(
aptId, docID, staffId, dTitle, tNo, aptExecutive)))),
),
body:
//SafeArea(
Center(
child: SafeArea(
child: SingleChildScrollView(
child: Container(
alignment: Alignment.center,
child: FutureBuilder<Appointment>(
future: futureAppointments,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasData) {
return Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.all(7),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
//height: 80.0,
width:
MediaQuery.of(context).size.width * 0.9,
child: TextFormField(
minLines: 1,
maxLines: 3,
readOnly: true,
// autovalidateMode:
// AutovalidateMode.onUserInteraction,
inputFormatters: [
LengthLimitingTextInputFormatter(100),
FilteringTextInputFormatter.allow(
RegExp(
"[,-/ a-z A-Z á-ú Á-Ú 0-9]")),
],
style: TextStyle(fontSize: 12),
keyboardType: TextInputType.name,
controller: docTitleController =
TextEditingController(
text: '${this.dTitle}'),
decoration: const InputDecoration(
errorStyle:
const TextStyle(fontSize: 0.05),
border: OutlineInputBorder(),
labelText: 'Document Title',
hintText: 'Document Title required',
),
validator: MultiValidator([
RequiredValidator(
errorText: 'Required*')
]),
),
),
Navigator.of(context).push(
MaterialPageRoute(
builder:
(BuildContext context) =>
AppointmentDetails(
aptId,
docID,
staffId,
dTitle,
tNo,
aptExecutive)));
AppointmentController
Future<Appointment> createAppointment(
int? aptId,
int? docId,
int staffId,
//String docTitle,
// String tokenNo,
String partyName,
String contactNo,
String partyType,
String aptPlace,
String city,
int? feesCollected,
int totalFees,
String paymentMode,
String aptDate,
String aptTime,
// String aptExecutive,
String aptStatus,
String comments,
// String createdAt,
) async {
final response = await http.put(
// Uri.parse('http://192.168.0.134:8080/AtdochubJ-3/appointment/register'),
Uri.parse('http://3.108.194.111:8080/AtdochubJ-3/appointment/register'
// 'http://3.108.194.111:8080/AtdochubJ-3/appointment/register'
),
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, dynamic>{
'aptId': aptId,
'docId': docId,
'staffId': staffId,
'partyName': partyName,
'contactNo': contactNo,
'partyType': partyType,
'aptPlace': aptPlace,
'city': city,
'feesCollected': feesCollected!,
'totalFees': totalFees,
'paymentMode': paymentMode,
'aptDate': aptDate,
'aptTime': aptTime,
//'aptExecutive': aptExecutive,
'aptStatus': aptStatus,
'comments': comments,
// 'createdAt': createdAt,
}));
if (response.statusCode == 200 || response.statusCode == 201) {
return Appointment.fromJson(jsonDecode(response.body)[0]);
else{
throw Exception(' Failed To Create Appointment');
}
AppointmentDetailPage
class AppointmentDetails extends StatefulWidget {
final int aptId;
final int staff_Id;
late final int docID;
final String dTitle;
final int tNo;
final String aptExecutive;
// final String doctitle;
// final String docToken;
AppointmentDetails(this.aptId, this.staff_Id, this.docID, this.dTitle,
this.tNo, this.aptExecutive);
#override
_AppointmentDetailsState createState() => _AppointmentDetailsState(
this.aptId,
this.staff_Id,
this.docID,
this.dTitle,
this.tNo,
this.aptExecutive,
);
}
class _AppointmentDetailsState extends State<AppointmentDetails> {
AppointmentController appointmentController =
Get.put(AppointmentController());
late Future<Appointment> futureAppointments;
final int aptId;
final int staff_Id;
final int docID;
final String dTitle;
final int tNo;
final String aptExecutive;
_AppointmentDetailsState(this.aptId, this.staff_Id, this.docID, this.dTitle,
this.tNo, this.aptExecutive);
#override
void initState() {
super.initState();
// print('detail staff ID $staff_Id');
// print('detail doc ID $docId');
print('apt detail...... $aptId, $dTitle, $tNo, $aptExecutive');
futureAppointments =
AppointmentController.fetchAppointmentsById(this.aptId);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color.fromARGB(255, 3, 87, 156),
title: Text('Appointment Details'),
leading: IconButton(
icon: BackButtonIcon(),
onPressed: () => Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => AppointmentPageFE()))),
),
body: Center(
child: FutureBuilder<Appointment>(
future: futureAppointments,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView(children: [
SafeArea(
child: SingleChildScrollView(
child: Container(
padding: EdgeInsets.all(15),
height: 750,
child: SelectionArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Document Title: ' + this.dTitle,
style: const TextStyle(fontSize: 15.0)),
Navigator.of(context)
.pushAndRemoveUntil(
MaterialPageRoute(
builder: (BuildContext
context) =>
AppointmentDetailsEditPage(
this.aptId,
this.docID,
this.staff_Id,
this.dTitle,
this.tNo,
this.aptExecutive,
)),
(Route<dynamic> route) =>
false);
},
),

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 : sort multidimensional array List

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

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