Currently, I am developing a desktop application in which I have saved the data in the database, now problem is that I am facing difficulties in listing the saved data on to screen. Below are the complete code files.
database_helper.dart
class DatabaseHelper {
final databaseName = "auth.db";
String newphase = '''
CREATE TABLE IF NOT EXISTS newphase(
srNo INTEGER PRIMARY KEY AUTOINCREMENT,
phaseName TEXT,
landinAcers INTEGER,
landinmarlas INTEGER,
description TEXT
)
''';
Future<Database> initDB() async {
print("initDB executed");
try {
String databaseName = 'auth.db';
final databasePath = await getDatabasesPath();
final path = join(databasePath, databaseName);
return openDatabase(path, version: 2, onCreate: (db, version) async {
await db.execute(newphase);
});
}catch (e) {
print("Error initializing database: $e");
rethrow;
}
}
Future<int> addNewPhase(NewPhase newphase) async {
final Database db = await initDB();
return db.insert('newphase', newphase.toMap());
}
Future<List<Map<String, dynamic>>> getPhases() async {
final Database db = await initDB();
List<Map<String, Object?>> data = await db.query('newphase',);
print("Data is " + data.toString());
Map newPhase = data[0];
print("Sr No is ${newphase[0].toString()}");
print("Name is ${newphase[1].toString()}");
return data;
}
}
newphase_json.dart
import 'dart:convert';
NewPhase newPhaseFromMap(String str) => NewPhase.fromMap(json.decode(str));
String newPhaseToMap(NewPhase data) => json.encode(data.toMap());
class NewPhase {
final int? srNo;
final String phaseName;
final String landInAcers;
final String landInMarlas;
final String description;
NewPhase({
this.srNo,
required this.phaseName,
required this.landInAcers,
required this.landInMarlas,
required this.description,
});
factory NewPhase.fromMap(Map<String, dynamic> json) => NewPhase(
srNo: json["srNo"],
phaseName: json["phaseName"],
landInAcers: json["landInAcers"],
landInMarlas: json["landInMarlas"],
description: json["description"],
);
Map<String, dynamic> toMap() => {
"srNo": srNo,
"phaseName": phaseName,
"landInAcers": landInAcers,
"landInMarlas": landInMarlas,
"description": description,
};
}
add_new_phase_form.dart
import '../../SQLite/newphase_json.dart';
import '../../utils/app_layout.dart';
import '../../utils/dependencies.dart';
import '../../widgets/elevated_button.dart';
import '../../SQLite/database_helper.dart';
class AddNewPhaseForm extends StatefulWidget {
const AddNewPhaseForm({super.key});
@override
_AddNewPhaseFormState createState() => _AddNewPhaseFormState();
}
class _AddNewPhaseFormState extends State<AddNewPhaseForm> {
final _formKey = GlobalKey<FormState>();
final phaseName = TextEditingController();
final landInAcers = TextEditingController();
final landInMarlas = TextEditingController();
final description = TextEditingController();
final DatabaseHelper db = DatabaseHelper();
var homeController = Get.put(HomeController());
addnewphase() async {
var res = await db.addNewPhase(NewPhase(
phaseName: phaseName.text,
landInAcers: landInAcers.text, landInMarlas: landInMarlas.text,
description: description.text,
));
if (res > 0) {
if (!mounted) return;
homeController.changeIndex(1);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Record added successfully!'),
duration: Duration(seconds: 5), // Adjust duration as needed
),
);
}
}
@override
Widget build(BuildContext context) {
final size = AppLayout.getSize(context);
return Container(
width: size.width * 1,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15), color: Colors.white),
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Add New Phase',
style: TextStyle(
fontSize: 18,
fontFamily: 'Quicksand-SemiBold',
fontWeight: FontWeight.w500,
color: Colors.black,
),
),
const SizedBox(height: 30),
Form(
key: _formKey,
child: Column(
children: [
TextFormField(
controller: phaseName,
decoration: const InputDecoration(
labelText: 'Phase Name',
border: OutlineInputBorder(),
),
validator: (value) {
if (value!.isEmpty) {
return 'Please enter phase name';
}
return null;
},
),
const SizedBox(height: 20),
TextFormField(
keyboardType: TextInputType.number,
controller: landInAcers,
decoration: const InputDecoration(labelText: 'Land In Acers', border: OutlineInputBorder(),),
validator: (value) {
if (value!.isEmpty) {
return 'Please enter land in acers';
}
return null;
},
),
const SizedBox(height: 20),
TextFormField(
controller: landInMarlas,
decoration: const InputDecoration(labelText: 'Land in Marlas', border: OutlineInputBorder(),),
validator: (value) {
if (value!.isEmpty) {
return 'Please enter Land in Marlas';
}
return null;
},
),
const SizedBox(height: 20),
TextFormField(
controller: description,
keyboardType: TextInputType.number,
decoration: const InputDecoration(labelText: 'Description', border: OutlineInputBorder(),),
validator: (value) {
if (value!.isEmpty) {
return 'Please enter Description';
}
return null;
},
),
const SizedBox(height: 20),
CustomElevatedButton(
width: 100,
height: 50,
backgroundColor: Colors.blue,
text: 'Add New',
style: const TextStyle(
fontSize: 16,
color: Colors.white,
fontFamily: 'Quicksand-SemiBold',
fontWeight: FontWeight.w500
),
onPressed: (){
addnewphase();
print('record added...');
}
),
],
),
),
],
),
),
);
}
}
phase_list.dart
import '../../tabels/add_new_phase_list.dart';
import '../../utils/app_layout.dart';
import '../../utils/dependencies.dart';
class PhaseListScreen extends StatelessWidget {
const PhaseListScreen({super.key});
@override
Widget build(BuildContext context) {
final size = AppLayout.getSize(context);
return Padding(
padding: const EdgeInsets.all(20.0),
child: Scaffold(
backgroundColor: const Color(0xffF2F7FB),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
children: [
Container(
height: 45,
width: 45,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Colors.blue
),
child: const Icon(Icons.landscape, color: Colors.white),
),
const SizedBox(width: 20),
const Text(
'Phase List',
style: TextStyle(
fontSize: 18,
fontFamily: 'Quicksand-SemiBold',
fontWeight: FontWeight.w500,
color: Colors.black,
),
),
],
),
const SizedBox(height: 30),
NewAddedPahseList(),
],
)
),
);
}
}
add_new_phase_list.dart
import 'package:flutter/cupertino.dart';
import 'package:new_city/SQLite/database_helper.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import '../utils/app_layout.dart';
import '../utils/dependencies.dart';
class NewAddedPahseList extends StatefulWidget {
NewAddedPahseList({Key? key}) : super(key: key);
@override
_NewAddedPahseListState createState() => _NewAddedPahseListState();
}
class _NewAddedPahseListState extends State<NewAddedPahseList> {
late List<Map> newPhases;
late PhasesDataSource phasesDataSource;
var homeController = Get.put(HomeController());
@override
void initState() {
super.initState();
newPhases = getPhaseData() as List<Map>;
phasesDataSource = PhasesDataSource(phaseData: newPhases);
}
final TextEditingController _searchController = TextEditingController();
String _searchText = '';
@override
Widget build(BuildContext context) {
final size = AppLayout.getSize(context);
return Container(
width: size.width * 1,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15), color: Colors.white),
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
InkWell(
onTap: () {
homeController.changeIndex(30);
},
child: Container(
width: 100,
height: 45,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Colors.blue
),
child: const Center(
child: Text(
'Add New',
style: TextStyle(
fontWeight: FontWeight.w400,
fontSize: 18,
fontFamily: 'Quicksand-Regular',
color: Colors.white
),
),
),
),
),
const SizedBox(height: 30),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
SizedBox(
width: 300,
child: TextField(
controller: _searchController,
decoration: const InputDecoration(
labelText: 'Search',
hintText: 'Enter your search query',
border: OutlineInputBorder(),
),
onChanged: (value) {
setState(() {
_searchText = value;
});
},
),
),
],
),
const SizedBox(height: 30),
SfDataGrid(
source: phasesDataSource,
columnWidthMode: ColumnWidthMode.fill,
allowSorting: true,
allowMultiColumnSorting: true,
sortingGestureType: SortingGestureType.tap,
rowsPerPage: 0,
columns: <GridColumn>[
GridColumn(
columnName: 'serNo',
label: Container(
padding: const EdgeInsets.all(8.0),
alignment: Alignment.centerLeft,
child: const Text('Sr. No' , style:
TextStyle(
fontFamily: 'Quicksand-SemiBold',
fontSize: 18,
fontWeight: FontWeight.w500,
color: Colors.black,
),),
),
),
GridColumn(
columnName: 'name',
label: Container(
padding: const EdgeInsets.all(8.0),
alignment: Alignment.centerLeft,
child: const Text('Phase Name', style:
TextStyle(
fontFamily: 'Quicksand-SemiBold',
fontSize: 18,
fontWeight: FontWeight.w500,
color: Colors.black,
),
),
),
),
GridColumn(
columnName: 't_area',
label: Container(
padding: const EdgeInsets.all(16.0),
alignment: Alignment.centerLeft,
child: const Text(
'Total Area in Acers',style:
TextStyle(
fontFamily: 'Quicksand-SemiBold',
fontSize: 18,
fontWeight: FontWeight.w500,
color: Colors.black,
),
))),
GridColumn(
columnName: 't_plot',
label: Container(
padding: const EdgeInsets.all(8.0),
alignment: Alignment.centerLeft,
child: const Text(
'Total Plot', style:
TextStyle(
fontFamily: 'Quicksand-SemiBold',
fontSize: 18,
fontWeight: FontWeight.w500,
color: Colors.black,
),
//overflow: TextOverflow.ellipsis,
))),
GridColumn(
columnName: 'action',
label: Container(
padding: const EdgeInsets.all(8.0),
alignment: Alignment.centerLeft,
child: const Text('Action' , style:
TextStyle(
fontFamily: 'Quicksand-SemiBold',
fontSize: 18,
fontWeight: FontWeight.w500,
color: Colors.black,
),),
),
),
],
),
SfDataPager(pageCount: 5, delegate: DataPagerDelegate()),
],
),
),
);
}
Future<List<Map>> getPhaseData() async {
return await DatabaseHelper().getPhases();
}
}
/// Custom business object class which contains properties to hold the detailed
/// information about the employee which will be rendered in datagrid.
class NewPhases {
NewPhases(this.serNo, this.name, this.t_area, this.t_plot, this.price);
final int serNo;
final String name;
final int t_area;
final int t_plot;
final int price;
}
/// An object to set the employee collection data source to the datagrid. This
/// is used to map the employee data to the datagrid widget.
class PhasesDataSource extends DataGridSource {
/// Creates the employee data source class with required details.
PhasesDataSource({required List<Map> phaseData}) {
_phaseData = phaseData
.map<DataGridRow>((e) => DataGridRow(cells: [
DataGridCell<int>(columnName: 'serNo', value: e.length),
DataGridCell<String>(columnName: 'name', value: e.toString()),
DataGridCell<int>(columnName: 't_area', value: e.length),
DataGridCell<int>(columnName: 't_plot', value: e.length),
DataGridCell<int>(columnName: 'action', value: e.length),
])).toList();
}
List<DataGridRow> _phaseData = [];
@override
List<DataGridRow> get rows => _phaseData;
@override
DataGridRowAdapter buildRow(DataGridRow row) {
return DataGridRowAdapter(
cells: row.getCells().map<Widget>((e) {
return Container(
alignment: Alignment.topLeft,
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 15),
child:e.columnName == 'action'?Row(
children: [
GestureDetector(
onTap: (){},
child: const Icon(Icons.edit, color: Colors.blue,),
),
const SizedBox(width:10),
GestureDetector(
onTap: (){},
child: const Icon(Icons.delete, color: Colors.red,),
),
],
):Text(e.value.toString(), style: const TextStyle(
fontFamily: 'Quicksand-Regular',
fontSize: 16,
fontWeight: FontWeight.w400,
color: Color(0xff2f2e2e),
),
),
);
}).toList());
}
}
Currently, the data is saving successfully but faces an issue in listing the data
the initState method cannot be async
so,on your NewAddedPahseList
widget
create a new method like this
fetchInitData() async {
newPhases =await getPhaseData();
phasesDataSource = PhasesDataSource(phaseData: newPhases);
setState((){});
}
and call this method on initState
@override
void initState() {
phasesDataSource = PhasesDataSource(phaseData: newPhases);
fetchInitData();
super.initState();
}
You need to handle the asynchronous nature of the Future to access its value.
and replace
late List<Map> newPhases;
by:
List<Map> newPhases=[];