Receiving Null check operator used on a null value error - flutter

I've been facing errors regarding my Syncfusion Calendar. Just recently, I was not able to initialize my _startDate and _endDate variables but some people suggested to make it nullable which I did but now it is giving me "Null check operator used on a null value" error.
Calendar Code:
class EventCalendar extends StatefulWidget {
const EventCalendar({Key? key}) : super(key: key);
#override
EventCalendarState createState() => EventCalendarState();
}
List<Color> _colorCollection = <Color>[];
List<String> _colorNames = <String>[];
int _selectedColorIndex = 0;
late DataSource _events;
Meeting? _selectedAppointment;
DateTime? _startDate;
DateTime? _endDate;
late TimeOfDay _startTime;
late TimeOfDay _endTime;
bool _isAllDay = false;
String _subject = '';
String _notes = '';
class EventCalendarState extends State<EventCalendar> {
EventCalendarState(); //check
CalendarView _calendarView = CalendarView.month;
late List<String> eventNameCollection;
late List<Meeting> appointments;
#override
void initState() {
_calendarView = CalendarView.month;
appointments = getMeetingDetails();
_events = DataSource(appointments);
_selectedAppointment = null;
_selectedColorIndex = 0;
_subject = '';
_notes = '';
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: UserDrawer(),
appBar: AppBar(
iconTheme: IconThemeData(color: Colors.black),
backgroundColor: Colors.transparent,
elevation: 0,
centerTitle: true,
title: const Text('Itinerary',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
color: Colors.black)),
),
resizeToAvoidBottomInset: false,
body: Padding(
padding: const EdgeInsets.fromLTRB(5, 0, 5, 5),
child: getEventCalendar(_calendarView, _events)),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add, color: Colors.white),
backgroundColor: Color(0xFF003893),
onPressed: () => Navigator.push<Widget>(
context,
MaterialPageRoute(
builder: (BuildContext context) => EventEditor()),
)));
}
SfCalendar getEventCalendar(
CalendarView _calendarView,
CalendarDataSource _calendarDataSource,
) {
return SfCalendar(
view: _calendarView,
backgroundColor: Colors.transparent,
initialSelectedDate: DateTime.now(),
todayHighlightColor: Color(0xFF003893),
selectionDecoration: BoxDecoration(color: Colors.white60),
showNavigationArrow: true,
cellBorderColor: Colors.transparent,
firstDayOfWeek: 1,
allowedViews: [
CalendarView.day,
CalendarView.week,
CalendarView.month,
CalendarView.timelineWeek
],
monthViewSettings: MonthViewSettings(
showAgenda: true,
agendaViewHeight: 250,
appointmentDisplayMode: MonthAppointmentDisplayMode.appointment),
dataSource: _calendarDataSource,
initialDisplayDate: DateTime(DateTime.now().year, DateTime.now().month,
DateTime.now().day, 0, 0, 0),
timeSlotViewSettings: TimeSlotViewSettings(
minimumAppointmentDuration: const Duration(minutes: 60)),
);
}
void onCalendarViewChange(String value) {
if (value == 'Day') {
_calendarView = CalendarView.day;
} else if (value == 'Week') {
_calendarView = CalendarView.week;
} else if (value == 'Month') {
_calendarView = CalendarView.month;
} else if (value == 'Timeline week') {
_calendarView = CalendarView.timelineWeek;
}
setState(() {});
}
List<Meeting> getMeetingDetails() {
final List<Meeting> meetingCollection = <Meeting>[];
eventNameCollection = <String>[];
eventNameCollection.add('');
_colorCollection = <Color>[];
_colorCollection.add(const Color(0xFF3D4FB5));
_colorCollection.add(const Color(0xFF0F8644));
_colorCollection.add(const Color(0xFF8B1FA9));
_colorCollection.add(const Color(0xFFD20100));
_colorCollection.add(const Color(0xFFFC571D));
_colorCollection.add(const Color(0xFF85461E));
_colorCollection.add(const Color(0xFFFF00FF));
_colorCollection.add(const Color(0xFFE47C73));
_colorCollection.add(const Color(0xFF636363));
_colorNames = <String>[];
_colorNames.add('Blue');
_colorNames.add('Green');
_colorNames.add('Purple');
_colorNames.add('Red');
_colorNames.add('Orange');
_colorNames.add('Caramel');
_colorNames.add('Magenta');
_colorNames.add('Peach');
_colorNames.add('Gray');
return meetingCollection;
}
}
class DataSource extends CalendarDataSource {
DataSource(List<Meeting> source) {
appointments = source;
}
#override
bool isAllDay(int index) => appointments![index].isAllDay;
#override
String getSubject(int index) => appointments![index].eventName;
#override
String getNotes(int index) => appointments![index].description;
#override
Color getColor(int index) => appointments![index].background;
#override
DateTime getStartTime(int index) => appointments![index].from;
#override
DateTime getEndTime(int index) => appointments![index].to;
}
class Meeting {
Meeting(
{required this.from,
required this.to,
this.background = Colors.green,
this.isAllDay = false,
this.eventName = '',
this.description = ''});
final String eventName;
final DateTime from;
final DateTime to;
final Color background;
final bool isAllDay;
final String description;
}
Add/Edit/Delete Event in Calendar Code:
class EventEditorState extends State<EventEditor> {
Widget _getAppointmentEditor(BuildContext context) {
return Container(
color: Colors.white,
child: ListView(
padding: const EdgeInsets.all(12),
children: <Widget>[
ListTile(
contentPadding: const EdgeInsets.fromLTRB(10, 0, 0, 0),
title: TextFormField(
controller: TextEditingController(text: _subject),
onChanged: (String value) {
_subject = value;
},
keyboardType: TextInputType.multiline,
maxLines: null,
style: TextStyle(
fontSize: 15,
color: Colors.black,
fontWeight: FontWeight.w400),
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Title',
),
),
),
const Divider(
height: 1.0,
thickness: 1,
),
ListTile(
contentPadding: const EdgeInsets.all(5),
leading: Icon(
Icons.subject,
color: Colors.black87,
),
title: TextField(
controller: TextEditingController(text: _notes),
onChanged: (String value) {
_notes = value;
},
keyboardType: TextInputType.multiline,
maxLines: null,
style: TextStyle(
fontSize: 15,
color: Colors.black87,
fontWeight: FontWeight.w400),
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Add description',
),
),
),
const Divider(
height: 1.0,
thickness: 1,
),
ListTile(
contentPadding: const EdgeInsets.fromLTRB(10, 15, 20, 2),
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('From', style: TextStyle(fontWeight: FontWeight.w500)),
SizedBox(height: 5),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 7,
child: GestureDetector(
child: Text(
DateFormat('EEE, MMM dd yyyy')
.format(_startDate!),
textAlign: TextAlign.left),
onTap: () async {
final DateTime? date = await showDatePicker(
context: context,
initialDate: _startDate!,
firstDate: DateTime(1900),
lastDate: DateTime(2100),
);
if (date != null && date != _startDate) {
setState(() {
final Duration difference =
_endDate!.difference(_startDate!);
_startDate = DateTime(
date.year,
date.month,
date.day,
_startTime.hour,
_startTime.minute,
0);
_endDate = _startDate!.add(difference);
_endTime = TimeOfDay(
hour: _endDate!.hour,
minute: _endDate!.minute);
});
}
}),
),
Expanded(
flex: 3,
child: _isAllDay
? const Text('')
: GestureDetector(
child: Text(
DateFormat('hh:mm a')
.format(_startDate!),
textAlign: TextAlign.right,
),
onTap: () async {
final TimeOfDay? time =
await showTimePicker(
context: context,
initialTime: TimeOfDay(
hour: _startTime.hour,
minute: _startTime.minute));
if (time != null &&
time != _startTime) {
setState(() {
_startTime = time;
final Duration difference =
_endDate!
.difference(_startDate!);
_startDate = DateTime(
_startDate!.year,
_startDate!.month,
_startDate!.day,
_startTime.hour,
_startTime.minute,
0);
_endDate =
_startDate!.add(difference);
_endTime = TimeOfDay(
hour: _endDate!.hour,
minute: _endDate!.minute);
});
}
})),
]),
],
)),
ListTile(
contentPadding: const EdgeInsets.fromLTRB(10, 5, 20, 2),
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('To', style: TextStyle(fontWeight: FontWeight.w500)),
SizedBox(height: 5),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
flex: 7,
child: GestureDetector(
child: Text(
DateFormat('EEE, MMM dd yyyy')
.format(_endDate!),
textAlign: TextAlign.left,
),
onTap: () async {
final DateTime? date = await showDatePicker(
context: context,
initialDate: _endDate!,
firstDate: DateTime(1900),
lastDate: DateTime(2100),
);
if (date != null && date != _endDate) {
setState(() {
final Duration difference =
_endDate!.difference(_startDate!);
_endDate = DateTime(
date.year,
date.month,
date.day,
_endTime.hour,
_endTime.minute,
0);
if (_endDate!.isBefore(_startDate!)) {
_startDate =
_endDate!.subtract(difference);
_startTime = TimeOfDay(
hour: _startDate!.hour,
minute: _startDate!.minute);
}
});
}
}),
),
Expanded(
flex: 3,
child: _isAllDay
? const Text('')
: GestureDetector(
child: Text(
DateFormat('hh:mm a').format(_endDate!),
textAlign: TextAlign.right,
),
onTap: () async {
final TimeOfDay? time =
await showTimePicker(
context: context,
initialTime: TimeOfDay(
hour: _endTime.hour,
minute: _endTime.minute));
if (time != null && time != _endTime) {
setState(() {
_endTime = time;
final Duration difference =
_endDate!
.difference(_startDate!);
_endDate = DateTime(
_endDate!.year,
_endDate!.month,
_endDate!.day,
_endTime.hour,
_endTime.minute,
0);
if (_endDate!
.isBefore(_startDate!)) {
_startDate = _endDate!
.subtract(difference);
_startTime = TimeOfDay(
hour: _startDate!.hour,
minute: _startDate!.minute);
}
});
}
})),
]),
],
)),
SizedBox(height: 10),
ListTile(
contentPadding: const EdgeInsets.fromLTRB(10, 5, 20, 2),
leading: Icon(
Icons.access_time,
color: Colors.black54,
),
title: Row(children: <Widget>[
const Expanded(
child: Text('All-day'),
),
Expanded(
child: Align(
alignment: Alignment.centerRight,
child: Switch(
value: _isAllDay,
onChanged: (bool value) {
setState(() {
_isAllDay = value;
});
},
))),
])),
const Divider(
height: 1.0,
thickness: 1,
),
ListTile(
contentPadding: const EdgeInsets.fromLTRB(10, 5, 20, 2),
leading: Icon(Icons.lens,
color: _colorCollection[_selectedColorIndex]),
title: Text(
_colorNames[_selectedColorIndex],
),
onTap: () {
showDialog<Widget>(
context: context,
barrierDismissible: true,
builder: (BuildContext context) {
return _ColorPicker();
},
).then((dynamic value) => setState(() {}));
},
),
const Divider(
height: 1.0,
thickness: 1,
),
],
));
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: Text(getTile()),
backgroundColor: _colorCollection[_selectedColorIndex],
leading: IconButton(
icon: const Icon(
Icons.close,
color: Colors.white,
),
onPressed: () {
Navigator.pop(context);
},
),
actions: <Widget>[
IconButton(
padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
icon: const Icon(
Icons.done,
color: Colors.white,
),
onPressed: () {
final List<Meeting> meetings = <Meeting>[];
if (_selectedAppointment != null) {
_events.appointments!.removeAt(_events.appointments!
.indexOf(_selectedAppointment));
_events.notifyListeners(CalendarDataSourceAction.remove,
<Meeting>[]..add(_selectedAppointment!));
}
meetings.add(Meeting(
from: _startDate!,
to: _endDate!,
background: _colorCollection[_selectedColorIndex],
description: _notes,
isAllDay: _isAllDay,
eventName: _subject == '' ? '(No Title)' : _subject,
));
_events.appointments!.add(meetings[0]);
_events.notifyListeners(
CalendarDataSourceAction.add, meetings);
_selectedAppointment = null;
Navigator.pop(context);
})
],
),
body: Padding(
padding: const EdgeInsets.fromLTRB(5, 5, 5, 5),
child: Stack(
children: <Widget>[_getAppointmentEditor(context)],
),
),
floatingActionButton: _selectedAppointment == null
? const Text('')
: FloatingActionButton(
onPressed: () {
if (_selectedAppointment != null) {
_events.appointments!.removeAt(_events.appointments!
.indexOf(_selectedAppointment));
_events.notifyListeners(CalendarDataSourceAction.remove,
<Meeting>[]..add(_selectedAppointment!));
_selectedAppointment = null;
Navigator.pop(context);
}
},
child:
const Icon(Icons.delete_outline, color: Colors.white),
backgroundColor: Colors.red,
)));
}
String getTile() {
return _subject.isEmpty ? 'New event' : 'Event details';
}
}
How do I solve this issue?

Related

How to Fetching data from sql database in flutter between two date?

in flutter and sqflite i created this function to calculate the total of price in colPrix.
I want to calculate total prices between two dates (period time) by pick and choose the date of start and the end date every time want to calculate the total .
What shoud i do ?
1/function calculate Total in database (where i create database).
class DatabaseHelper {
static DatabaseHelper _databaseHelper; // Singleton DatabaseHelper
static Database _database; // Singleton Database
String clientTable = 'client_table';
String colId = 'id';
String colNumerotelephone = 'numerotelephone';
String colCode = 'code';
String colPrix = 'prix';
String colPriority = 'priority';
String colColor = 'color';
String colDate = 'date';
DatabaseHelper._createInstance();
factory DatabaseHelper() {
if (_databaseHelper == null) {_databaseHelper = DatabaseHelper._createInstance(); // This is executed only once, singleton object}
return _databaseHelper;
}
Future<Database> get database async {
if (_database == null) { _database = await initializeDatabase();}
return _database;
}
.....
.....
Future claculTotalPeriod (String startDate, String endDate) async {
var totalClientperiod = await database;
var result = await totalClientperiod.rawQuery("SELECT SUM($colPrix) AS TOTAL from $clientTable WHERE $colDate BETWEEN '$startDate' AND '$endDate'");
return result.toList();
}
}
2/display the result
class ClientList extends StatefulWidget {
const ClientList({Key key}) : super(key: key);
#override
State<StatefulWidget> createState() {
return ClientListState();
}
}
class ClientListState extends State<ClientList> {
DatabaseHelper databaseHelper = DatabaseHelper();
List<Client> clientList;
int count = 0;
int axisCount = 2;
double somme_period = 00;
String somme_total_period = "00.00";
String startDate='';
String endDate='';
TextEditingController startdate = TextEditingController();
TextEditingController finishdate = TextEditingController();
void calcul_total_period() async {
var total_sum_period = (await databaseHelper.claculTotalPeriod(startDate, endDate))[0]['$startDate''$endDate'];
setState(() {
somme_period = total_sum_period ?? 00;
somme_total_period = somme.toStringAsFixed(2);
});
}
#override
Widget build(BuildContext context) {
if (clientList == null) {
clientList = [];
updateListView();
}
return Scaffold(
appBar: myAppBar(),
body: clientList.isEmpty
? Container(
color: Colors.white,
child: Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text('add+',
style: Theme.of(context).textTheme.bodyText2),
),
),
)
: Container(
color: Colors.white,
child: getClientsList(),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
navigateToDetail(Client('', '', '', 3, 0, 0.0), 'new');
},
tooltip: 'add',
shape: const CircleBorder(
side: BorderSide(color: Colors.black, width: 2.0)),
child: const Icon(Icons.add, color: Colors.black),
backgroundColor: Colors.white,
),
bottomNavigationBar: OutlinedButton(
onPressed: () {
showDialog(
...
child: Column(
TextField(
controller: startdate,
decoration: const InputDecoration(
icon: Icon(Icons.calendar_today
),
onTap: () async {
DateTime pickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2022,12),
lastDate: DateTime(2026,12));
if (pickedDate != null) {
print(
pickedDate);
String formattedDate =
DateFormat('yyyy-MM-dd').format(pickedDate);
print(
formattedDate); //formatted date output using intl package => 2021-03-16
setState(() {
startdate.text =
formattedDate;
startDate = startdate.text.toString();
});
} else {}
},
),
const SizedBox(height: 20,),
TextField(
controller: finishdate,
decoration: const InputDecoration(
icon: Icon(Icons.calendar_today), //icon of text field
),
onTap: () async {
DateTime pickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2022,12),
lastDate: DateTime(2026,12));
if (pickedDate != null) {
print(
pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000
String formattedDate =
DateFormat('yyyy-MM-dd').format(pickedDate);
print(
formattedDate); //formatted date output using intl package => 2021-03-16
setState(() {
finishdate.text =
formattedDate; //set output date to TextField value.
endDate = finishdate.text.toString();
});
} else {}
},
),
const SizedBox(height: 20,),
OutlinedButton(
onPressed: () {
calcul_total_period();
},
child: const Text(' total in period')),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
somme_total_period,
style: Theme.of(context).textTheme.headline5,
textAlign: TextAlign.center,
),
),
],
),
),
);
});
},
child: const Text('total')),
);
}
Widget getClientsList() {
return StaggeredGridView.countBuilder(
physics: const BouncingScrollPhysics(),
crossAxisCount: 4,
itemCount: count,
itemBuilder: (BuildContext context, int index) => GestureDetector(
onTap: () {
navigateToDetail(clientList[index], 'edit');
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
padding: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
color: colors[clientList[index].color],
border: Border.all(width: 2, color: Colors.black),
borderRadius: BorderRadius.circular(8.0)),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
clientList[index].numerotelephone,
style: Theme.of(context).textTheme.bodyText2,
),
),
),
Text(
getPriorityText(clientList[index].priority),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
clientList[index].code,
style: Theme.of(context).textTheme.bodyText2,
),
),
),
],
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
child: Text(clientList[index].prix.toString() ?? 0,
style: Theme.of(context).textTheme.bodyText1),
)
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text(clientList[index].date,
style: Theme.of(context).textTheme.subtitle2),
])
],
),
),
),
),
staggeredTileBuilder: (int index) => StaggeredTile.fit(axisCount),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
);
}
void navigateToDetail(Client client, String title) async {
bool result = await Navigator.push(context,
MaterialPageRoute(builder: (context) => ClientDetail(client, title)));
if (result == true) {
updateListView();
}
}
void updateListView() {
final Future<Database> dbFuture = databaseHelper.initializeDatabase();
dbFuture.then((database) {
Future<List<Client>> clientListFuture = databaseHelper.getClientList();
clientListFuture.then((clientList) {
setState(() {
this.clientList = clientList;
count = clientList.length;
});
});
});
}
}
You can do like this
List<Map> results = await dbClient.rawQuery(
"SELECT SUM(col) as TOTAL "
"FROM MyTable "
"AND dateTimeStamp >= ? "
"AND dateTimeStamp <= ? "
"ORDER BY dateTimeStamp ASC ",
[fromTimestamp,toTimeStamp]);

Not able to remove focus from input field

I have four textfields, a title field, a details field, a date field, and a time field. Both the date and time fields are wrapped within a gesture detector, and onTap calls a pickDateAndTime method. The problem is that when I click on the date field and try to manually change the time through the input rather than the dial way, the focus goes to the title field and when I am still on the time picker and type something in the time picker, the title field gets changed with the new input. The weird part is that this error just appeared out of nowhere, and there are no errors reported in the console.
class TodoScreen extends StatefulWidget {
final int? todoIndex;
final int? arrayIndex;
const TodoScreen({Key? key, this.todoIndex, this.arrayIndex})
: super(key: key);
#override
State<TodoScreen> createState() => _TodoScreenState();
}
class _TodoScreenState extends State<TodoScreen> {
final ArrayController arrayController = Get.find();
final AuthController authController = Get.find();
final String uid = Get.find<AuthController>().user!.uid;
late TextEditingController _dateController;
late TextEditingController _timeController;
late TextEditingController titleEditingController;
late TextEditingController detailEditingController;
late String _setTime, _setDate;
late String _hour, _minute, _time;
late String dateTime;
late bool done;
#override
void initState() {
super.initState();
String title = '';
String detail = '';
String date = '';
String? time = '';
if (widget.todoIndex != null) {
title = arrayController
.arrays[widget.arrayIndex!].todos![widget.todoIndex!].title ??
'';
detail = arrayController
.arrays[widget.arrayIndex!].todos![widget.todoIndex!].details ??
'';
date = arrayController
.arrays[widget.arrayIndex!].todos![widget.todoIndex!].date!;
time = arrayController
.arrays[widget.arrayIndex!].todos![widget.todoIndex!].time;
}
_dateController = TextEditingController(text: date);
_timeController = TextEditingController(text: time);
titleEditingController = TextEditingController(text: title);
detailEditingController = TextEditingController(text: detail);
done = (widget.todoIndex == null)
? false
: arrayController
.arrays[widget.arrayIndex!].todos![widget.todoIndex!].done!;
}
DateTime selectedDate = DateTime.now();
TimeOfDay selectedTime = TimeOfDay(
hour: (TimeOfDay.now().minute > 55)
? TimeOfDay.now().hour + 1
: TimeOfDay.now().hour,
minute: (TimeOfDay.now().minute > 55) ? 0 : TimeOfDay.now().minute + 5);
Future<DateTime?> _selectDate() => showDatePicker(
builder: (context, child) {
return datePickerTheme(child);
},
initialEntryMode: DatePickerEntryMode.calendarOnly,
context: context,
initialDate: selectedDate,
initialDatePickerMode: DatePickerMode.day,
firstDate: DateTime.now(),
lastDate: DateTime(DateTime.now().year + 5));
Future<TimeOfDay?> _selectTime() => showTimePicker(
builder: (context, child) {
return timePickerTheme(child);
},
context: context,
initialTime: selectedTime,
initialEntryMode: TimePickerEntryMode.input);
Future _pickDateTime() async {
DateTime? date = await _selectDate();
if (date == null) return;
if (date != null) {
selectedDate = date;
_dateController.text = DateFormat("MM/dd/yyyy").format(selectedDate);
}
TimeOfDay? time = await _selectTime();
if (time == null) {
_timeController.text = formatDate(
DateTime(
DateTime.now().year,
DateTime.now().day,
DateTime.now().month,
DateTime.now().hour,
DateTime.now().minute + 5),
[hh, ':', nn, " ", am]).toString();
}
if (time != null) {
selectedTime = time;
_hour = selectedTime.hour.toString();
_minute = selectedTime.minute.toString();
_time = '$_hour : $_minute';
_timeController.text = _time;
_timeController.text = formatDate(
DateTime(2019, 08, 1, selectedTime.hour, selectedTime.minute),
[hh, ':', nn, " ", am]).toString();
}
}
#override
Widget build(BuildContext context) {
bool visible =
(_dateController.text.isEmpty && _timeController.text.isEmpty)
? false
: true;
final formKey = GlobalKey<FormState>();
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Text((widget.todoIndex == null) ? 'New Task' : 'Edit Task',
style: menuTextStyle),
leadingWidth: (MediaQuery.of(context).size.width < 768) ? 90.0 : 100.0,
leading: Center(
child: Padding(
padding: (MediaQuery.of(context).size.width < 768)
? const EdgeInsets.only(left: 0)
: const EdgeInsets.only(left: 21.0),
child: TextButton(
style: const ButtonStyle(
splashFactory: NoSplash.splashFactory,
),
onPressed: () {
Get.back();
},
child: Text(
"Cancel",
style: paragraphPrimary,
),
),
),
),
centerTitle: true,
actions: [
Center(
child: Padding(
padding: (MediaQuery.of(context).size.width < 768)
? const EdgeInsets.only(left: 0)
: const EdgeInsets.only(right: 21.0),
child: TextButton(
style: const ButtonStyle(
splashFactory: NoSplash.splashFactory,
),
onPressed: () async {
},
child: Text((widget.todoIndex == null) ? 'Add' : 'Update',
style: paragraphPrimary),
),
),
)
],
),
body: SafeArea(
child: Container(
width: double.infinity,
padding: (MediaQuery.of(context).size.width < 768)
? const EdgeInsets.symmetric(horizontal: 15.0, vertical: 20.0)
: const EdgeInsets.symmetric(horizontal: 35.0, vertical: 15.0),
child: Column(
children: [
Form(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
validator: Validator.titleValidator,
controller: titleEditingController,
autofocus: true, // problem here
autocorrect: false,
cursorColor: Colors.grey,
maxLines: 1,
maxLength: 25,
textInputAction: TextInputAction.next,
decoration: InputDecoration(
counterStyle: counterTextStyle,
hintStyle: hintTextStyle,
hintText: "Title",
border: InputBorder.none),
style: todoScreenStyle),
primaryDivider,
TextField(
controller: detailEditingController,
maxLines: null,
autocorrect: false,
cursorColor: Colors.grey,
textInputAction: TextInputAction.done,
decoration: InputDecoration(
counterStyle: counterTextStyle,
hintStyle: hintTextStyle,
hintText: "Notes",
border: InputBorder.none),
style: todoScreenDetailsStyle),
],
),
),
Visibility(
visible: (widget.todoIndex != null) ? true : false,
child: GestureDetector(
onTap: () {},
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Completed",
style: todoScreenStyle,
),
Transform.scale(
scale: 1.3,
child: Theme(
data: ThemeData(
unselectedWidgetColor: const Color.fromARGB(
255, 187, 187, 187)),
child: Checkbox(
shape: const CircleBorder(),
checkColor: Colors.white,
activeColor: primaryColor,
value: done,
side: Theme.of(context).checkboxTheme.side,
onChanged: (value) {
setState(() {
done = value!;
});
})),
)
],
),
),
),
GestureDetector(
onTap: () async {
await _pickDateTime();
setState(() {
visible = true;
});
},
child: Column(
children: [
Row(
children: [
Flexible(
child: TextField(
enabled: false,
controller: _dateController,
onChanged: (String val) {
_setDate = val;
},
decoration: InputDecoration(
hintText: "Date",
hintStyle: hintTextStyle,
border: InputBorder.none),
style: todoScreenStyle,
),
),
visible
? IconButton(
onPressed: () {
_dateController.clear();
_timeController.clear();
setState(() {});
},
icon: const Icon(
Icons.close,
color: Colors.white,
))
: Container()
],
),
primaryDivider,
TextField(
onChanged: (String val) {
_setTime = val;
},
enabled: false,
controller: _timeController,
decoration: InputDecoration(
hintText: "Time",
hintStyle: hintTextStyle,
border: InputBorder.none),
style: todoScreenStyle,
)
],
),
),
],
),
),
),
);
}
}
Should I open an issue on Github, as I had not made any changes to the code for it behave this way and also because there were no errors in the console
Here is the full code on Github
Update
Here is a reproducible example:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const TodoScreen(),
);
}
}
class TodoScreen extends StatefulWidget {
const TodoScreen({Key? key}) : super(key: key);
#override
State<TodoScreen> createState() => _TodoScreenState();
}
class _TodoScreenState extends State<TodoScreen> {
late TextEditingController _dateController;
late TextEditingController _timeController;
late TextEditingController titleEditingController;
late TextEditingController detailEditingController;
late String _setTime, _setDate;
late String _hour, _minute, _time;
late String dateTime;
#override
void initState() {
super.initState();
String title = '';
String detail = '';
String date = '';
String? time = '';
_dateController = TextEditingController(text: date);
_timeController = TextEditingController(text: time);
titleEditingController = TextEditingController(text: title);
detailEditingController = TextEditingController(text: detail);
}
#override
void dispose() {
super.dispose();
titleEditingController.dispose();
detailEditingController.dispose();
_timeController.dispose();
_dateController.dispose();
}
Theme timePickerTheme(child) => Theme(
data: ThemeData.dark().copyWith(
timePickerTheme: TimePickerThemeData(
backgroundColor: const Color.fromARGB(255, 70, 70, 70),
dayPeriodTextColor: Colors.green,
hourMinuteTextColor: MaterialStateColor.resolveWith((states) =>
states.contains(MaterialState.selected)
? Colors.white
: Colors.white),
dialHandColor: Colors.green,
helpTextStyle: TextStyle(
fontSize: 12, fontWeight: FontWeight.bold, color: Colors.green),
dialTextColor: MaterialStateColor.resolveWith((states) =>
states.contains(MaterialState.selected)
? Colors.white
: Colors.white),
entryModeIconColor: Colors.green,
),
textButtonTheme: TextButtonThemeData(
style: ButtonStyle(
foregroundColor:
MaterialStateColor.resolveWith((states) => Colors.green)),
),
),
child: child!,
);
Theme datePickerTheme(child) => Theme(
data: ThemeData.dark().copyWith(
colorScheme: ColorScheme.dark(
surface: Colors.green,
secondary: Colors.green,
onPrimary: Colors.white,
onSurface: Colors.white,
primary: Colors.green,
)),
child: child!,
);
DateTime selectedDate = DateTime.now();
TimeOfDay selectedTime = TimeOfDay(
hour: (TimeOfDay.now().minute > 55)
? TimeOfDay.now().hour + 1
: TimeOfDay.now().hour,
minute: (TimeOfDay.now().minute > 55) ? 0 : TimeOfDay.now().minute + 5);
Future<DateTime?> _selectDate() => showDatePicker(
builder: (context, child) {
return datePickerTheme(child);
},
initialEntryMode: DatePickerEntryMode.calendarOnly,
context: context,
initialDate: selectedDate,
initialDatePickerMode: DatePickerMode.day,
firstDate: DateTime.now(),
lastDate: DateTime(DateTime.now().year + 5));
Future<TimeOfDay?> _selectTime() => showTimePicker(
builder: (context, child) {
return timePickerTheme(child);
},
context: context,
initialTime: selectedTime,
initialEntryMode: TimePickerEntryMode.input);
Future _pickDateTime() async {
DateTime? date = await _selectDate();
if (date == null) return;
if (date != null) {
selectedDate = date;
_dateController.text = selectedDate.toString();
}
TimeOfDay? time = await _selectTime();
if (time != null) {
selectedTime = time;
_hour = selectedTime.hour.toString();
_minute = selectedTime.minute.toString();
_time = '$_hour : $_minute';
_timeController.text = _time;
_timeController.text =
DateTime(2019, 08, 1, selectedTime.hour, selectedTime.minute)
.toString();
}
}
#override
Widget build(BuildContext context) {
bool visible =
(_dateController.text.isEmpty && _timeController.text.isEmpty)
? false
: true;
final formKey = GlobalKey<FormState>();
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
centerTitle: true,
),
body: SafeArea(
child: Container(
width: double.infinity,
padding: (MediaQuery.of(context).size.width < 768)
? const EdgeInsets.symmetric(horizontal: 15.0, vertical: 20.0)
: const EdgeInsets.symmetric(horizontal: 35.0, vertical: 15.0),
child: Column(
children: [
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(14.0)),
padding: const EdgeInsets.symmetric(
horizontal: 24.0, vertical: 15.0),
child: Form(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
controller: titleEditingController,
autofocus: true,
autocorrect: false,
cursorColor: Colors.grey,
maxLines: 1,
maxLength: 25,
textInputAction: TextInputAction.next,
decoration: InputDecoration(
hintText: "Title", border: InputBorder.none),
),
Divider(color: Colors.black),
TextField(
controller: detailEditingController,
maxLines: null,
autocorrect: false,
cursorColor: Colors.grey,
textInputAction: TextInputAction.done,
decoration: InputDecoration(
hintText: "Notes", border: InputBorder.none),
),
],
),
)),
GestureDetector(
onTap: () async {
await _pickDateTime();
setState(() {
visible = true;
});
},
child: Container(
margin: const EdgeInsets.only(top: 20.0),
width: double.infinity,
padding: const EdgeInsets.symmetric(
horizontal: 24.0, vertical: 15.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(14.0)),
child: Column(
children: [
Row(
children: [
Flexible(
child: TextField(
enabled: false,
controller: _dateController,
onChanged: (String val) {
_setDate = val;
},
decoration: InputDecoration(
hintText: "Date", border: InputBorder.none),
),
),
visible
? IconButton(
onPressed: () {
_dateController.clear();
_timeController.clear();
setState(() {});
},
icon: const Icon(
Icons.close,
color: Colors.white,
))
: Container()
],
),
Divider(
color: Colors.blue,
),
TextField(
onChanged: (String val) {
_setTime = val;
},
enabled: false,
controller: _timeController,
decoration: InputDecoration(
hintText: "Enter", border: InputBorder.none),
)
],
)),
),
],
),
),
),
);
}
}
In your main.dart file, you should return something like this:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
// This allows closing keyboard when tapping outside of a text field
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus &&
currentFocus.focusedChild != null) {
FocusManager.instance.primaryFocus!.unfocus();
}
},
child: // your app's entry point,
);
}
}
Add a focusNode in your textField:
FocusNode focusNode = FocusNode();
TextField(
focusNode: focusNode,
);
And then in the gesture detector, add that following code to unselect the textfield input:
FocusScope.of(context).requestFocus(FocusNode());
simply wrap your Scaffold widget GestureDetector and add FocusScope.of(context).requestFocus(FocusNode()); it will automatically unfocused text field when you click anywhere on your screen
GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(FocusNode());
},
child: Scaffold()
)
You can use below code to remove focus in gesture detector event
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus && currentFocus.focusedChild != null) {
currentFocus.unfocus();
}

how to build sorted listview in flutter (sort as per dates)

I want to display a listview from database. The notes stored in 'note' table are displayed successully. I want to display it as per the dates. i.e recent ones at the top and later ones(future ones) below them. if the date is of tomorrow then it should be at the top and day after tomorrow one below it. If the dates are same I want to sort them as per priority. Can anyone please help me.
(If u use any other date and time picker which can accept date and time together would also be helpful). In my case the table calendar only accepts the date. I am storing the date as TEXT(i dont know if its right)
new_note.dart// this is where I add a new note to the database.
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
import 'package:table_calendar/table_calendar.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:smooth_star_rating/smooth_star_rating.dart';
import 'package:intl/intl.dart';
import 'package:vers2cts/models/color_dropdown.dart';
import 'package:vers2cts/models/customer_model.dart';
import 'package:vers2cts/models/note_model.dart';
import 'package:vers2cts/services/db_service.dart';
import 'package:vers2cts/utils/form_helper.dart';
class NewNote extends StatefulWidget{
final NoteModel note;
final CustomerModel customer;
NewNote(this.customer,this. note);
#override
State<StatefulWidget> createState() {
return New_NoteState(this.customer,this.note);
}
}
class New_NoteState extends State<NewNote> with SingleTickerProviderStateMixin{
New_NoteState(this.customer,this.note);
NoteModel note=new NoteModel();
CustomerModel customer=new CustomerModel();
TextEditingController NoteController=TextEditingController();
TextEditingController custfNameController = TextEditingController();
DateTime _reminderDate = DateTime.now();
DateTime _selectedDay = DateTime.now();
DBService dbService=new DBService();
double _height;
double _width;
dynamic currentTime = DateFormat.jm().format(DateTime.now());
String _setTime, _setDate;
String _hour, _minute, _time;
String dateTime;
DateTime selectedDate = DateTime.now();
TimeOfDay selectedTime = TimeOfDay(hour: 00, minute: 00);
TextEditingController _dateController = TextEditingController();
TextEditingController _timeController = TextEditingController();
SpeedDial _speedDial(){
return SpeedDial(
animatedIcon: AnimatedIcons.add_event,
animatedIconTheme: IconThemeData(size: 24.0),
backgroundColor: Colors.yellow,
curve: Curves.easeInCirc,
children: [
SpeedDialChild(
child: Icon(Icons.location_on,color: Colors.yellow,),
label: 'Add Location',
),
SpeedDialChild(
child: Icon(Icons.keyboard_voice),
label: 'Add voice',
),
SpeedDialChild(
child: Icon(Icons.attachment_outlined,color :Colors.redAccent),
label: 'Add File',
),
SpeedDialChild(
child: Icon(Icons.image,color: Colors.lightBlue,),
label: 'Add Image',
),
],
);
}
//for Switch
bool isSwitched = false;
var textValue = 'Switch is OFF';
void toggleSwitch(bool value) {
if(isSwitched == false)
{
setState(() {
isSwitched = true;
note.rmnd_ind=1;
});
}
else
{
setState(() {
isSwitched = false;
note.rmnd_ind=0;
});
}
}
Future<Null> _selectTime(BuildContext context) async {
final TimeOfDay picked = await showTimePicker(
context: context,
initialTime: selectedTime,
);
if (picked != null)
setState(() {
selectedTime = picked;
_hour = selectedTime.hour.toString();
_minute = selectedTime.minute.toString();
_time = _hour + ' : ' + _minute;
_timeController.text = _time;
});
}
#override
void initState() {
_timeController.text=currentTime;
super.initState();
}
#override
Widget build(BuildContext context) {
var height = MediaQuery.of(context).size.height;
var width = MediaQuery.of(context).size.width;
var name=customer.first_name+" "+customer.last_name;
custfNameController.text = name;
String _chosenValue;
return WillPopScope(
onWillPop: () {navigationBar
moveToLastScreen();
},
child: Scaffold(
appBar:AppBar(),
body:ListView(
children: <Widget>[
SizedBox(
height: 2.0,
),
TextField(controller: custfNameController,
style: TextStyle(
fontSize: 20.0, fontWeight: FontWeight.bold),
textAlign: TextAlign.center),
Align(
alignment: Alignment.centerLeft,
child: Text("Add New",textAlign: TextAlign.left,
style: TextStyle(fontSize: 22,fontWeight: FontWeight.bold),),
),
SizedBox(
height: 2.0,
),
Divider(),
SizedBox(
height: 2.0,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: NoteController,
decoration: InputDecoration(
border: OutlineInputBorder(
borderSide: const BorderSide(width: 2.0),)),
keyboardType: TextInputType.multiline,
minLines: 5,//Normal textInputField will be displayed
maxLines: 5, // when user presses enter it will adapt to it
onChanged: (value) {
this.note.note = value;
},
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: TableCalendar(
selectedDayPredicate: (day) {
return isSameDay(_selectedDay, day);
},
onDaySelected: (selectedDay, focusedDay) {
setState(() {
_selectedDay=selectedDay;
String _reminderDate = DateFormat('dd-MM-yyyy').format(_selectedDay);
note.actn_on=_reminderDate.toString();
});
},// Set initial date
focusedDay: DateTime.now(),
firstDay: DateTime.utc(2010, 10, 16),
lastDay: DateTime.utc(2030, 3, 14),),
),
Row(
children: <Widget>[
Expanded(child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text("Set time",style: TextStyle(fontSize: 20),),
)),
Expanded(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: InkWell(
onTap: () {
_selectTime(context);
},
child: TextFormField(
style: TextStyle(fontSize: 30),
textAlign: TextAlign.center,
onSaved: (String val) {
_setTime = val;
},
enabled: false,
keyboardType: TextInputType.text,
controller: _timeController,
),
),
),
),
]
),
SizedBox(
height: height*0.03,
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
children: <Widget>[
Text("Remind me",style: TextStyle(fontSize: 20),),
Padding(
padding: const EdgeInsets.only(left:80.0),
child: Container(
child: Switch(
onChanged: toggleSwitch,
value: isSwitched,
),
),
),
],),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Row(mainAxisAlignment: MainAxisAlignment.start,
children:<Widget>[
Text("Priority",style: TextStyle(fontSize: 20.0),),
Padding(
padding: const EdgeInsets.only(left:20.0),
child: Container(
child: SmoothStarRating(
size: height=50.0,
allowHalfRating: false,
onRated: (value) {
this.note.prty=value;
print("rating value -> $value");
},
),
),
)]),
),
SizedBox(
height: height*0.08,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 55.0,
width: 200,
child: RaisedButton(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)),
color: Theme.of(context).primaryColorDark,
textColor: Colors.white,
child: Text('Save',textScaleFactor: 1.5,),
onPressed: (){
setState(() {
_save();
});
},
),
),
),
],
),
floatingActionButton:_speedDial(),
));
}
void moveToLastScreen() {
Navigator.pop(context, true);
}
void _save() async {
moveToLastScreen();
note.cust_id=customer.cust_id;
print(customer.cust_id);
print(note.cust_id);
int result;
if (note.note_id != null) { // Case 1: Update operation
result = await dbService.updateNote(note);
} else {
result = await dbService.insertNote(note);
}
if (result != 0) {
FormHelper.showAlertDialog(context,'Status', 'Note Saved Successfully');
} else {
FormHelper.showAlertDialog(context,'Status', 'Problem Saving Note');
}
}
}
note_info.dart // This is the screen which displays the listview
import 'dart:io';
import 'package:vers2cts/models/note_model.dart';
import 'package:vers2cts/models/customer_model.dart';
import 'package:vers2cts/services/db_service.dart';
import 'package:vers2cts/utils/db_helper.dart';
import 'package:flutter/material.dart';
import 'package:sqflite/sqflite.dart';
import 'package:vers2cts/utils/form_helper.dart';
import 'new_note.dart';
class Note_Info extends StatefulWidget{
final String appBarTitle;
final CustomerModel customer;
Note_Info(this. customer, this.appBarTitle);
#override
State<StatefulWidget> createState() {
return Note_InfoState(this. customer,this.appBarTitle);
}
}
class Note_InfoState extends State<Note_Info> {
DBService dbService = DBService();
List<NoteModel> noteList;
int count = 0;
static final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>();
NoteModel note=NoteModel();
String appBarTitle;
CustomerModel customer=new CustomerModel();
Note_InfoState(this.customer, this.appBarTitle);
bool rememberMe = false;
DateTime _date = DateTime.now();
TextEditingController custfNameController = TextEditingController();
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
updateListView();
if (noteList == null) {
noteList = List<NoteModel>();
updateListView();
}
TextStyle titleStyle = Theme.of(context).textTheme.subhead;
var height = MediaQuery.of(context).size.height;
var name=customer.first_name+" "+customer.last_name;
custfNameController.text = name;
return DefaultTabController(
length: 4,
child: Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: Icon(
Icons.add,
),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => NewNote(customer,note)));
},
)
],
),
body: Container(
child: Column(
children: <Widget>[
TextField(controller: custfNameController,
style: TextStyle(
fontSize: 20.0, fontWeight: FontWeight.bold),
textAlign: TextAlign.center),
Padding(
padding: const EdgeInsets.all(15.0),
child: Row(children: [
ImageProfile(customer.cust_photo),
Padding(
padding: const EdgeInsets.only(left: 30.0),
child: IconButton(
icon: Icon(
Icons.call,
color: Colors.green,
size: 45,
),
onPressed: () {
},
),
),
],),
),
SizedBox(
height: 50,
child: AppBar(
bottom: TabBar(
tabs: [
Tab(
text: "All",
),
Tab(
text: "Pending",
),
Tab(
text: "Cancelled",
),
Tab(
text: "Completed",
),
],
),
),
),
// create widgets for each tab bar here
Expanded(
child: TabBarView(
children: [
// first tab bar view widget
Container(
child: getNotecheckList()
),
// second tab bar viiew widget
Container(
),
Container(
child: Center(
child: Text(
'Cancelled',
),
),
),
Container(
child: Center(
child: Text(
'Completed',
),
),
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 55.0,
width: 200,
child: RaisedButton(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)),
color: Theme
.of(context)
.primaryColorDark,
textColor: Colors.white,
child: Text('Save', textScaleFactor: 1.5,),
onPressed: () {
setState(() {
//_reset();
});
},
),
),
),
]
),
)
));
}
Widget ImageProfile(String fileName) {
return Center(
child: CircleAvatar(
radius: 80.0,
backgroundImage: fileName == null
?AssetImage('images/person_icon.jpg')
:FileImage(File(customer.cust_photo))),
);
}
ListView getNoteListView() {
TextStyle titleStyle = Theme.of(context).textTheme.subhead;
return ListView.builder(
itemCount: count,
itemBuilder: (BuildContext context, int position) {
return Card(
color: Colors.white,
elevation: 2.0,
child: ListTile(
title: Text(this.noteList[position].note, style: titleStyle,),
//subtitle: Text(this.customerList[position].date),
trailing: GestureDetector(
child: Icon(Icons.delete, color: Colors.grey,),
onTap: () {
// _delete(context, customerList[position]);
},
),
onTap: () {
//navigateToDetail(this.customerList[position],'Edit ');
},
),
);
},
);
}
Future<void> updateListView() {
final Future<Database> dbFuture = DB.init();
dbFuture.then((database) {
int cid=customer.cust_id;
Future<List<NoteModel>> noteListFuture = dbService.getCustomerNotes(cid);
noteListFuture.then((noteList) {
setState(() {
this.noteList = noteList;
this.count = noteList.length;
});
});
});
}
int _isChecked=-1;
var selectedIndices = [];
ListView getNotecheckList() {
return ListView.builder(
itemCount: count,
itemBuilder: (BuildContext context, int position) {
return Card(
color: Colors.white,
elevation: 2.0,
child: CheckboxListTile(
title: Text(this.noteList[position].note),
subtitle: Text(this.noteList[position].actn_on),
value: selectedIndices.contains(position),
onChanged: (_) {
if (selectedIndices.contains(position)) {
selectedIndices.remove(position);// unselect
} else {
selectedIndices.add(position); // select
}
},
controlAffinity: ListTileControlAffinity.leading,
),
);
},
);
}
}
}
note_model.dart
import 'model.dart';
class NoteModel extends Model {
static String table = 'note';
bool isSelected=false;
int note_id;
int cust_id;
String note;
String actn_on;
int rmnd_ind;
double prty;
String colr;
String sts;
int id;
String cre_date;
String cre_by;
String mod_date;
String mod_by;
int txn_id;
int delete_ind;
NoteModel({
this.note_id,
this.cust_id,
this.note,
this.actn_on,
this.rmnd_ind,
this.prty,
this.colr,
this.sts,
this.id,
this.cre_date,
this.cre_by,
this.mod_date,
this.mod_by,
this.txn_id,
this.delete_ind
});
static NoteModel fromMap(Map<String, dynamic> map) {
return NoteModel(
note_id: map["note_id"],
cust_id: map['cust_id'],
note: map['note'].toString(),
actn_on: map['actn_on'].toString(),
rmnd_ind: map['rmnd_ind'],
prty: map['prty'],
colr: map['colr'].toString(),
sts: map['sts'].toString(),
id: map['id'],
cre_date: map['cre_date'].toString(),
cre_by: map['cre_by'].toString(),
mod_date: map['mod_date'].toString(),
mod_by: map['mod_by'].toString(),
txn_id: map['txn_id'],
delete_ind: map['delete_ind'],
);
}
Map<String, dynamic> toMap() {
Map<String, dynamic> map = {
'note_id': note_id,
'cust_id': cust_id,
'note':note,
'actn_on': actn_on,
'rmnd_ind': rmnd_ind,
'prty': prty,
'colr': colr,
'sts':sts,
'id': id,
'cre_date': cre_date,
'cre_by': cre_by,
'mod_date':mod_date,
'mod_by':mod_by,
'txn_id':txn_id,
'delete_ind': delete_ind
};
if (note_id != null) {
map['note_id'] = note_id;
}
return map;
}
}
db_service.dart
import 'package:vers2cts/models/note_model.dart';
import 'package:vers2cts/utils/db_helper.dart';
class DBService {
Future<int> insertNote(NoteModel note) async {
await DB.init();
var result = await DB.insert(NoteModel.table, note);
return result;
}
Future<List<Map<String, dynamic>>> getNoteMapList() async {
await DB.init();
var result = await DB.query(NoteModel.table);
return result;
}
Future<List<NoteModel>> getCustomerNotes(int customer) async {
await DB.init();
var res = await DB.rawQuery("note WHERE cust_id = '$customer'");
int count = res.length;
List<NoteModel> notelist = List<NoteModel>();
for (int i = 0; i < count; i++) {
notelist.add(NoteModel.fromMap(res[i]));
}
return notelist;
}
}
db_helper.dart actn_on saves the date and prty saves the priority
import 'dart:async';
import 'package:vers2cts/models/model.dart';
import 'package:path/path.dart' as p;
import 'package:sqflite/sqflite.dart';
abstract class DB {
static Database _db;
static int get _version => 1;
static Future<Database> init() async {
if (_db != null) {
return _db;
}
try {
var databasesPath = await getDatabasesPath();
String _path = p.join(databasesPath, 'CTS.db');
_db = await openDatabase(_path, version: _version, onCreate: onCreate);
print('db location:'+_path);
} catch (ex) {
print(ex);
}
}
static void onCreate(Database db, int version) async {
await db.execute(
'CREATE TABLE note (note_id INTEGER PRIMARY KEY,cust_id INTEGER, '
'note TEXT, '
'actn_on TEXT, rmnd_ind INTEGER, prty REAL, colr TEXT,'
'sts TEXT,'
'id INTEGER, cre_date TEXT,cre_by TEXT, mod_date TEXT,mod_by TEXT, txn_id INTEGER, delete_ind INTEGER)');
}
static Future<List<Map<String, dynamic>>> query(String table) async =>
_db.query(table);
static Future<int> insert(String table, Model model) async =>
await _db.insert(table, model.toMap());
static Future<List<Map<String, dynamic>>> rawQuery(String table) async =>
_db.query(table);
}
Thankyou DarShan I got my answer I just had to use ORDER BY in my query
Future<List<NoteModel>> getCustomerNotes(int customer) async {
await DB.init();
var res = await DB.rawQuery("note WHERE cust_id = '$customer' ORDER BY actn_on ASC,prty DESC;");
int count = res.length;
List<NoteModel> notelist = List<NoteModel>();
// For loop to create a 'Note List' from a 'Map List'
for (int i = 0; i < count; i++) {
notelist.add(NoteModel.fromMap(res[i]));
}
return notelist;
}

getting error " getter 'year' was called on null " when clearing textfield in flutter

here when I click on the clear button it will not clear the all the textbox only clearing the expiry_date field only and also showing me the exception "getter year was called on null".
in this code I have a clear button when I click on that button it will not clearing the button and showing year called on null. I think this problem happens because I've added onChanged in ExpiryDate widget. but I need an onChnaged event. so I need to clear everything. Hope you understand the question. Your help can make my day.
Here is the code :
class _BspLicensedSignupPageState extends State<BspLicensedSignupPage>
with AfterLayoutMixin<BspLicensedSignupPage> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final TextEditingController _bspBusinessLicenseNumber =
TextEditingController();
final TextEditingController _bspLicenseAuthorityName =
TextEditingController();
final TextEditingController _bspLicenseExpiryDate = TextEditingController();
final format = new DateFormat.yMMMEd('en-US');
String _isoDate;
List<BusinessProfilePicture> _bspLicenseImages =
new List<BusinessProfilePicture>();
List<Object> images = List<Object>();
List<dynamic> _bspLicenseAuthorityTypes = <dynamic>[];
Map<String, dynamic> _bspLicenseAuthorityType;
bool _isvisibleissuingauthority = false;
bool businesslicensecheck = false;
int radioValue = -1;
Future<File> licenceimage;
Future<File> profilepicture;
DateTime date;
TimeOfDay time;
String _countryId;
BSPSignupRepository _bspSignupRepository = new BSPSignupRepository();
bool autovalidate = false;
bool _isEditMode = false;
int selected = 0;
List<String> _imageFilesList = [];
var isUploadingPost = false;
var isEditInitialised = true;
List<File> _licenseImages = [];
#override
void initState() {
super.initState();
_scrollController = ScrollController();
}
Widget _buildbusinesslicenseno() {
return new TudoTextWidget(
prefixIcon: Icon(FontAwesomeIcons.idCard),
controller: _bspBusinessLicenseNumber,
labelText: AppConstantsValue.appConst['licensedsignup']
['businesslicenseno']['translation'],
validator: Validators().validateLicenseno,
);
}
Widget _buildexpirydate() {
return DateTimeField(
format: format,
autocorrect: true,
autovalidate: false,
controller: _bspLicenseExpiryDate,
readOnly: true,
validator: (date) => (date == null || _bspLicenseExpiryDate.text == '')
? 'Please enter valid date'
: null,
onChanged: (date) {
_isoDate = DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(date);
},
decoration: InputDecoration(
labelText: "Expiry Date",
hintText: "Expiry Date",
prefixIcon: Icon(
FontAwesomeIcons.calendar,
size: 24,
)),
onShowPicker: (context, currentValue) {
return showDatePicker(
context: context,
firstDate: DateTime.now(),
initialDate: currentValue ?? DateTime.now(),
lastDate: DateTime(2100),
);
},
);
}
Widget _buildlicenseauthority() {
return new TudoTextWidget(
validator: (val) => Validators.validateName(val, "Issuing Authority"),
controller: _bspLicenseAuthorityName,
prefixIcon: Icon(Icons.account_circle),
labelText: AppConstantsValue.appConst['licensedsignup']
['licenseissuingauthority']['translation'],
hintText: AppConstantsValue.appConst['licensedsignup']
['licenseissuingauthority']['translation'],
);
}
Widget _buildlabeluploadlicensepicture() {
return Text(AppConstantsValue.appConst['licensedsignup']
['labeluploadlicenpicture']['translation']);
}
Widget _buildlegalbusinesscheck() {
return TudoConditionWidget(
text: AppConstantsValue.appConst['licensedsignup']['legalbusinesscheck']
['translation'],
);
}
Widget content(
BuildContext context, BspLicensedSignupViewModel bspLicensedSignupVm) {
final appBar = AppBar(
centerTitle: true,
title: Text("BSP Licensed Details"),
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: () {
NavigationHelper.navigatetoBack(context);
},
),
);
final bottomNavigationBar = Container(
height: 56,
//margin: EdgeInsets.symmetric(vertical: 24, horizontal: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new FlatButton.icon(
icon: Icon(Icons.close),
label: Text('Clear'),
color: Colors.redAccent,
textColor: Colors.black,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7),
),
// onpress
onPressed: () {
_formKey.currentState.reset();
_bspBusinessLicenseNumber.clear();
_bspLicenseAuthorityName.clear();
_bspBusinessLicenseNumber.text = '';
_bspLicenseAuthorityName.text = '';
setState(() {
_licenseImages.clear();
_imageFilesList.clear();
});
},
),
new FlatButton.icon(
icon: Icon(FontAwesomeIcons.arrowCircleRight),
label: Text('Next'),
color: colorStyles["primary"],
textColor: Colors.white,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7),
),
onPressed: () async {
},
),
],
),
);
return new Scaffold(
appBar: appBar,
bottomNavigationBar: bottomNavigationBar,
body: Container(
height: double.infinity,
width: double.infinity,
child: Stack(
children: <Widget>[
// Background(),
SingleChildScrollView(
controller: _scrollController,
child: SafeArea(
top: false,
bottom: false,
child: Form(
autovalidate: autovalidate,
key: _formKey,
child: Scrollbar(
child: SingleChildScrollView(
dragStartBehavior: DragStartBehavior.down,
// padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: new Container(
margin: EdgeInsets.fromLTRB(30, 30, 30, 0),
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
_buildbusinesslicenseno(),
_buildexpirydate(),
_buildlegalbusinesscheck()
],
),
),
),
),
),
),
),
],
),
),
);
}
#override
Widget build(BuildContext context) {
return new StoreConnector<AppState, BspLicensedSignupViewModel>(
converter: (Store<AppState> store) =>
BspLicensedSignupViewModel.fromStore(store),
onInit: (Store<AppState> store) {
_countryId = store.state.auth.loginUser.user.country.id.toString();
print('_countryId');
print(_countryId);
},
builder: (BuildContext context,
BspLicensedSignupViewModel bspLicensedSignupVm) =>
content(context, bspLicensedSignupVm),
);
}
}
}
The formatter in the onChanged can't format a null date.
So you can add a null check in your DateTimeField's onChanged method.
Like this:
onChanged: (date) {
if (date != null){
_isoDate = DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(date);
}
}

image picker is not uploading image and it will send the null value to the backend

I've one page on that page there is one add button and it will add the widget as much users want but when I am uploading image it will not upload. and when I press the add button it will already upload the image on the next generated widget. and also it is not giving me the value of that images.
Here is the image it will upload image on the click of the image add button but it's not uploading. and also when I am adding multipart it will send the value as null to the backend side
Here is code i've tried.
class BspUnlicensedSignupPage extends StatefulWidget {
static const String routeName = "/bspUnlicensedSignup";
final BspSignupCommonModel bspSignupCommonModel;
BspUnlicensedSignupPage({
Key key,
#required this.bspSignupCommonModel,
}) : super(key: key);
#override
_BspUnlicensedSignupPageState createState() =>
_BspUnlicensedSignupPageState();
}
class _BspUnlicensedSignupPageState extends State<BspUnlicensedSignupPage> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
List<Object> images = List<Object>();
Future<File> _imageFile;
bool autovalidate = false;
bool informationislegitimate = false;
DateTime expirydate1 = DateTime.now();
DateTime expirydate2 = DateTime.now();
final format = DateFormat("yyyy-MM-dd");
final format2 = DateFormat("yyyy-MM-dd");
String type2 = 'Passport';
List<String> _type = <String>[
'',
'Passport',
'Driving License',
'Voter ID card',
'Ration Card',
'Aadhar',
'Other Id',
];
String type = 'Passport';
// Map<String, String> _formdata = {};
var _myWidgets = List<Widget>();
int _index = 1;
final Map<int, String> identification1Values = Map();
final Map<int, String> documentValues = Map();
final Map<int, DateTime> expiryDateValues = Map();
final Map<int, String> issuingAuthority = Map();
final Map<int, String> identificationPicturesValues = Map();
final List<TextEditingController> _documentControllers = List();
final List<TextEditingController> _issuingauthoritytype = List();
final List<TextEditingController> _expiryDate = List();
final List<TextEditingController> _issuingauthority = List();
final List<List<Object>> _identificationpictures = List();
#override
void initState() {
super.initState();
setState(() {
images.add("Add Image");
images.add("Add Image");
images.add("Add Image");
images.add("Add Image");
images.add("Add Image");
});
}
void _add() {
// TextEditingController controller = TextEditingController();
setState(() {
int keyValue = _myWidgets.length;
_myWidgets = List.from(_myWidgets)
..add(Column(
key: Key("$keyValue"),
children: <Widget>[
SizedBox(height: 10),
Container(
// padding: EdgeInsets.fromLTRB(18,5,18,18),
padding: EdgeInsets.all(15),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 15,
),
],
),
child: Column(
children: <Widget>[
Stack(
children: <Widget>[
Align(
alignment: Alignment.topRight,
child: GestureDetector(
child: Icon(Icons.close),
onTap: () {
print("CLose pressed");
setState(() {
_myWidgets = List.from(_myWidgets)
..removeAt(keyValue);
});
},
),
),
SizedBox(
height: 10,
),
Column(
children: <Widget>[
SizedBox(
height: 20,
),
_buildidentificationtype1(keyValue),
_builddocumentnumber1(keyValue),
_builddate(keyValue),
_buildissuingauthority1(keyValue),
_buildidentificationpictures(keyValue),
],
),
],
)
],
),
)
],
));
});
}
bool isClicked = false;
Widget _buildidentificationtype1(int keyValue) {
TextEditingController controller = TextEditingController();
_issuingauthoritytype.add(controller);
return FormBuilder(
autovalidate: autovalidate,
child: FormBuilderCustomField(
attribute: "Business type",
validators: [FormBuilderValidators.required()],
formField: FormField(
builder: (FormFieldState<dynamic> field) {
return InputDecorator(
decoration: InputDecoration(
prefixIcon: Icon(Icons.location_on),
labelText : 'Business type',
),
isEmpty: type == '',
child: new DropdownButtonHideUnderline(
child: new DropdownButton(
value: type,
isDense: true,
onChanged: (String newValue) {
setState(() {
type = controller.text = newValue;
field.didChange(newValue);
});
},
items: _type.map(
(String value) {
return new DropdownMenuItem(
value: value,
child: new Text(value),
);
},
).toList(),
),
),
);
},
)),
);
}
Widget _builddocumentnumber1(int keyValue) {
TextEditingController controller = TextEditingController();
_documentControllers.add(controller);
return new TudoTextWidget(
controller: controller,
prefixIcon: Icon(FontAwesomeIcons.idCard),
labelText : 'Document Number'
onSaved: (val) {
setState(() {
documentValues[keyValue] = val;
});
// _licenseno = val;
},
);
}
Widget _builddate(int keyValue) {
TextEditingController controller = TextEditingController();
_expiryDate.add(controller);
return DateTimeField(
format: format,
autocorrect: true,
autovalidate: autovalidate,
controller: controller,
readOnly: true,
// validator: (date) => date == null ? 'Please enter valid date' : null,
decoration: InputDecoration(
labelText: "Expiry Date",
hintText: "Expiry Date",
prefixIcon: Icon(
FontAwesomeIcons.calendar,
size: 24,
)),
onShowPicker: (context, currentValue) {
return showDatePicker(
context: context,
firstDate: DateTime.now(),
initialDate: currentValue ?? DateTime.now(),
lastDate: DateTime(2100));
},
);
}
Widget _buildissuingauthority1(int keyValue) {
TextEditingController controller = TextEditingController();
_issuingauthority.add(controller);
return new TudoTextWidget(
prefixIcon: Icon(FontAwesomeIcons.idCard),
labelText: 'Issuning authority',
validator: (val) => Validators.validateName(val, "Issuing Authority"),
onSaved: (val) {
setState(() {
issuingAuthority[keyValue] = val;
});
// _illusingauthority = issuingAuthority[keyValue] = val;
},
controller: controller,
);
}
Widget _buildidentificationpictures(int keyValue) {
return GridView.count(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
crossAxisCount: 5,
childAspectRatio: 1,
children: List.generate(images.length, (index) {
if (images[index] is ImageUploadModel) {
ImageUploadModel uploadModel = images[index];
return Card(
clipBehavior: Clip.antiAlias,
child: Stack(
children: <Widget>[
Image.file(
uploadModel.imageFile,
width: 300,
height: 300,
),
Positioned(
right: 5,
top: 5,
child: InkWell(
child: Icon(
Icons.remove_circle,
size: 20,
color: Colors.red,
),
onTap: () {
setState(() {
images.replaceRange(index, index + 1, ['Add Image']);
_identificationpictures.add(images);
});
},
),
),
],
),
);
} else {
return Card(
child: IconButton(
icon: Icon(Icons.add),
onPressed: () {
_onAddImageClick(index);
},
),
);
}
}),
);
}
Future _onAddImageClick(int index) async {
setState(() {
_imageFile = ImagePicker.pickImage(source: ImageSource.gallery);
getFileImage(index);
});
}
void getFileImage(int index) async {
// var dir = await path_provider.getTemporaryDirectory();
_imageFile.then((file) async {
setState(() {
ImageUploadModel imageUpload = new ImageUploadModel();
imageUpload.isUploaded = false;
imageUpload.uploading = false;
imageUpload.imageFile = file;
imageUpload.imageUrl = '';
images.replaceRange(index, index + 1, [imageUpload]);
});
});
}
Widget _buildinformationislegitmate() {
return TudoConditionWidget(
text:
"Above entered Identity information is legitimate and accurate to my knowledge",
);
}
#override
Widget build(BuildContext context) {
final appBar = AppBar(
title: Text("BSP Unlicensed Details"),
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
onPressed: () {
NavigationHelper.navigatetoBack(context);
},
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.add),
onPressed: () {
setState(() {
_add();
});
},
),
],
centerTitle: true,
);
final bottomNavigationBar = Container(
color: Colors.transparent,
height: 56,
//margin: EdgeInsets.symmetric(vertical: 24, horizontal: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new FlatButton.icon(
icon: Icon(Icons.close),
label: Text('Clear'),
color: Colors.redAccent,
textColor: Colors.black,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7),
),
onPressed: () {},
),
new FlatButton.icon(
icon: Icon(FontAwesomeIcons.arrowCircleRight),
label: Text('Next'),
color: colorStyles["primary"],
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 30),
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7),
),
onPressed: () async {
setState(() {
autovalidate = !autovalidate;
});
if (_formKey.currentState.validate()) {
List<Licensed> listOfLicenses = new List<Licensed>();
BspSignupCommonModel model = widget.bspSignupCommonModel;
for (var i = 0; i < _myWidgets.length; i++) {
String document = _documentControllers[i].text;
String issuingAuthorityType = _issuingauthoritytype[i].text;
String expiryDate = _expiryDate[i].text;
String issuingAuthority = _issuingauthority[i].text;
// String picture = _identificationpictures[i].text;
print('Document: $document');
print('IssuingAuthorityType: $issuingAuthorityType');
print('ExpiryDate: $expiryDate');
print('IssuingAuthority: $issuingAuthority');
print('Picture: ${_identificationpictures.length}');
print(_myWidgets.length);
Licensed licensed = new Licensed(
bspLicenseNumber: document,
bspAuthority: issuingAuthority,
bspExpiryDate: expiryDate,
bspIssuing: issuingAuthorityType,
);
licensed.bspLicenseNumber = _documentControllers[i].text;
licensed.bspExpiryDate = _expiryDate[i].text;
licensed.bspIssuing = _issuingauthoritytype[i].text;
licensed.bspAuthority = _issuingauthority[i].text;
listOfLicenses.add(licensed);
}
model.unlicensed = listOfLicenses;
print(model.toJson());
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BspLicensedSignupTermsPage(
bspSignupCommonModel: model),
));
}
}),
],
),
);
return new Scaffold(
appBar: appBar,
bottomNavigationBar: bottomNavigationBar,
floatingActionButton: new FloatingActionButton.extended(
onPressed: () {
_add();
},
label: Text(
"Add License",
style: TextStyle(color: Colors.white, fontSize: 16),
),
icon: Icon(
Icons.add,
size: 28,
color: Colors.white,
),
),
body: Container(
height: double.infinity,
width: double.infinity,
child: Form(
autovalidate: autovalidate,
key: _formKey,
child: Stack(
children: <Widget>[
Column(
children: <Widget>[
Expanded(
child: SizedBox(
child: ListView(
padding: const EdgeInsets.all(18.0),
children: _myWidgets,
),
),
),
_buildinformationislegitmate(),
],
)
],
)),
),
);
}
}
The problem seems to be that you are using the same list images for every item, you could try to use a Map that has the lists for each item.
I suggest you to try to create a separate widget with the entire card so it can handle it's own state.