Skip to content

Commit c940b89

Browse files
Merge pull request #1 from abineshPalanisamy/master
Added KB sample
2 parents 27c18e0 + 61fee67 commit c940b89

File tree

125 files changed

+4863
-2
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

125 files changed

+4863
-2
lines changed

.gitignore

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Miscellaneous
2+
*.class
3+
*.log
4+
*.pyc
5+
*.swp
6+
.DS_Store
7+
.atom/
8+
.buildlog/
9+
.history
10+
.svn/
11+
migrate_working_dir/
12+
13+
# IntelliJ related
14+
*.iml
15+
*.ipr
16+
*.iws
17+
.idea/
18+
19+
# The .vscode folder contains launch configuration and tasks you configure in
20+
# VS Code which you may wish to be included in version control, so this line
21+
# is commented out by default.
22+
#.vscode/
23+
24+
# Flutter/Dart/Pub related
25+
**/doc/api/
26+
**/ios/Flutter/.last_build_id
27+
.dart_tool/
28+
.flutter-plugins
29+
.flutter-plugins-dependencies
30+
.packages
31+
.pub-cache/
32+
.pub/
33+
/build/
34+
35+
# Symbolication related
36+
app.*.symbols
37+
38+
# Obfuscation related
39+
app.*.map.json
40+
41+
# Android Studio will place build artifacts here
42+
/android/app/debug
43+
/android/app/profile
44+
/android/app/release

README.md

Lines changed: 173 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,173 @@
1-
# how-to-implement-asynchronous-sorting-of-data-retrieved-from-firestore-in-a-flutter-data-table
2-
How to implement asynchronous sorting of data retrieved from Firestore in a Flutter DataTable (SfDataGrid)?
1+
# How to implement asynchronous sorting of data retrieved from Firestore in a Flutter DataTable (SfDataGrid)?
2+
3+
In this article, we will discuss how to implement asynchronous sorting in a [Flutter DataGrid](https://www.syncfusion.com/flutter-widgets/flutter-datagrid) that retrieves data from Firestore. We will cover the steps and techniques required to fetch data from Firestore, handle asynchronous operations, and dynamically sort the data based on user interactions.
4+
5+
## STEP 1:
6+
You need to add the following package in the dependencies of pubspec.yaml.
7+
8+
```dart
9+
firebase_core: ^2.13.0
10+
cloud_firestore: ^4.7.1
11+
12+
```
13+
14+
## STEP 2:
15+
Import the following library into the flutter application:
16+
17+
```dart
18+
import 'package:cloud_firestore/cloud_firestore.dart';
19+
import 'package:firebase_core/firebase_core.dart';
20+
21+
```
22+
23+
## STEP 3:
24+
Initialize the [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) with all the required details. Fetch the data from the Firestore database by passing the required collection name. The [StreamController](https://api.flutter.dev/flutter/dart-async/StreamController-class.html) that will be used to control the loading state. It will emit true or false values to show or hide the loading indicator.
25+
26+
```dart
27+
const defaultFirebaseOptions = FirebaseOptions(
28+
apiKey: '',
29+
authDomain: '',
30+
projectId: '',
31+
storageBucket: '',
32+
messagingSenderId: '',
33+
appId: '',
34+
);
35+
36+
StreamController<bool> loadingController = StreamController<bool>();
37+
38+
class SfDataGridDemo extends StatefulWidget {
39+
const SfDataGridDemo({Key? key}) : super(key: key);
40+
@override
41+
SfDataGridDemoState createState() => SfDataGridDemoState();
42+
}
43+
44+
class SfDataGridDemoState extends State<SfDataGridDemo> {
45+
late EmployeeDataSource employeeDataSource;
46+
List<Employee> employeeData = [];
47+
48+
@override
49+
void initState() {
50+
super.initState();
51+
employeeDataSource = EmployeeDataSource([]);
52+
}
53+
54+
final getDataFromFireStore =
55+
FirebaseFirestore.instance.collection('Sync1').snapshots();
56+
Widget _buildDataGrid() {
57+
return StreamBuilder<QuerySnapshot>(
58+
stream: getDataFromFireStore,
59+
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
60+
if (snapshot.hasData) {
61+
for (var data in snapshot.data!.docs) {
62+
employeeData.add(Employee(
63+
id: data['id'],
64+
name: data['name'],
65+
designation: data['designation'],
66+
salary: data['salary'].toString()));
67+
}
68+
employeeDataSource = EmployeeDataSource(employeeData);
69+
return StreamBuilder<bool>(
70+
stream: loadingController.stream,
71+
builder: (context, snapshot) {
72+
return Stack(children: [
73+
SfDataGrid(
74+
source: employeeDataSource,
75+
columns: getColumns,
76+
allowSorting: true,
77+
columnWidthMode: ColumnWidthMode.fill,
78+
gridLinesVisibility: GridLinesVisibility.both,
79+
headerGridLinesVisibility: GridLinesVisibility.both,
80+
),
81+
if (snapshot.data == true)
82+
const Center(
83+
child: CircularProgressIndicator(),
84+
),
85+
]);
86+
});
87+
} else {
88+
return const Center(
89+
child: CircularProgressIndicator(),
90+
);
91+
}
92+
},
93+
);
94+
}
95+
96+
@override
97+
Widget build(BuildContext context) {
98+
return Scaffold(
99+
appBar: AppBar(
100+
title: const Text('Syncfusion Flutter Datagrid FireStore Demo'),
101+
),
102+
body: _buildDataGrid(),
103+
);
104+
}
105+
}
106+
107+
```
108+
109+
## STEP 4:
110+
The performSorting method accepts a list of DataGridRow objects as input. It includes a simulated asynchronous that applies the [Future.delay](https://api.flutter.dev/flutter/dart-async/Future/Future.delayed.html) for a specific time to imitate server-side processing. Upon completion of the delay, the loadingController is updated to signal the end of loading. If the current column's sortDirection is set to ascending, the dataGridRow variable is assigned a new list of DataGridRow objects. Each row represents an employee, with cells containing their respective attributes. The isSuspend variable is then set to false, indicating the completion of the sorting process. If the sortDirection is descending, the same steps are followed.
111+
112+
```dart
113+
bool isSuspend = true;
114+
@override
115+
Future<void> performSorting(List<DataGridRow> rows) async {
116+
if (!isSuspend || sortedColumns.isEmpty) {
117+
return;
118+
}
119+
loadingController.add(true);
120+
await Future<void>.delayed(const Duration(seconds: 2));
121+
loadingController.add(false);
122+
123+
for (final column in sortedColumns) {
124+
if (column.sortDirection == DataGridSortDirection.ascending) {
125+
final snapshot = await FirebaseFirestore.instance
126+
.collection('Sync1')
127+
.orderBy(column.name)
128+
.get();
129+
fetchData(snapshot);
130+
buildData(employeeData);
131+
isSuspend = false;
132+
notifyListeners();
133+
} else if (column.sortDirection == DataGridSortDirection.descending) {
134+
final snapshot = await FirebaseFirestore.instance
135+
.collection('Sync1')
136+
.orderBy(column.name,
137+
descending:
138+
column.sortDirection == DataGridSortDirection.descending)
139+
.get();
140+
fetchData(snapshot);
141+
buildData(employeeData);
142+
isSuspend = false;
143+
notifyListeners();
144+
}
145+
}
146+
147+
isSuspend = true;
148+
}
149+
150+
List<Employee> fetchData(QuerySnapshot<Map<String, dynamic>> snapshot) {
151+
return employeeData = snapshot.docs
152+
.map((data) => Employee(
153+
id: data['id'],
154+
name: data['name'],
155+
designation: data['designation'],
156+
salary: data['salary'].toString(),
157+
))
158+
.toList();
159+
}
160+
161+
List<DataGridRow> buildData(List<Employee> employeeData) {
162+
return dataGridRows = employeeData
163+
.map<DataGridRow>((e) => DataGridRow(cells: [
164+
DataGridCell<String>(columnName: 'id', value: e.id),
165+
DataGridCell<String>(columnName: 'name', value: e.name),
166+
DataGridCell<String>(
167+
columnName: 'designation', value: e.designation),
168+
DataGridCell<String>(columnName: 'salary', value: e.salary),
169+
]))
170+
.toList();
171+
}
172+
173+
```

android/.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
gradle-wrapper.jar
2+
/.gradle
3+
/captures/
4+
/gradlew
5+
/gradlew.bat
6+
/local.properties
7+
GeneratedPluginRegistrant.java
8+
9+
# Remember to never publicly share your keystore.
10+
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11+
key.properties
12+
**/*.keystore
13+
**/*.jks

android/app/build.gradle

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
def localProperties = new Properties()
2+
def localPropertiesFile = rootProject.file('local.properties')
3+
if (localPropertiesFile.exists()) {
4+
localPropertiesFile.withReader('UTF-8') { reader ->
5+
localProperties.load(reader)
6+
}
7+
}
8+
9+
def flutterRoot = localProperties.getProperty('flutter.sdk')
10+
if (flutterRoot == null) {
11+
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12+
}
13+
14+
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15+
if (flutterVersionCode == null) {
16+
flutterVersionCode = '1'
17+
}
18+
19+
def flutterVersionName = localProperties.getProperty('flutter.versionName')
20+
if (flutterVersionName == null) {
21+
flutterVersionName = '1.0'
22+
}
23+
24+
apply plugin: 'com.android.application'
25+
apply plugin: 'kotlin-android'
26+
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27+
28+
android {
29+
namespace "com.example.flutter_application_1"
30+
compileSdkVersion flutter.compileSdkVersion
31+
ndkVersion flutter.ndkVersion
32+
33+
compileOptions {
34+
sourceCompatibility JavaVersion.VERSION_1_8
35+
targetCompatibility JavaVersion.VERSION_1_8
36+
}
37+
38+
kotlinOptions {
39+
jvmTarget = '1.8'
40+
}
41+
42+
sourceSets {
43+
main.java.srcDirs += 'src/main/kotlin'
44+
}
45+
46+
defaultConfig {
47+
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
48+
applicationId "com.example.flutter_application_1"
49+
// You can update the following values to match your application needs.
50+
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
51+
minSdkVersion flutter.minSdkVersion
52+
targetSdkVersion flutter.targetSdkVersion
53+
versionCode flutterVersionCode.toInteger()
54+
versionName flutterVersionName
55+
}
56+
57+
buildTypes {
58+
release {
59+
// TODO: Add your own signing config for the release build.
60+
// Signing with the debug keys for now, so `flutter run --release` works.
61+
signingConfig signingConfigs.debug
62+
}
63+
}
64+
}
65+
66+
flutter {
67+
source '../..'
68+
}
69+
70+
dependencies {
71+
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
72+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2+
<!-- The INTERNET permission is required for development. Specifically,
3+
the Flutter tool needs it to communicate with the running application
4+
to allow setting breakpoints, to provide hot reload, etc.
5+
-->
6+
<uses-permission android:name="android.permission.INTERNET"/>
7+
</manifest>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2+
<application
3+
android:label="flutter_application_1"
4+
android:name="${applicationName}"
5+
android:icon="@mipmap/ic_launcher">
6+
<activity
7+
android:name=".MainActivity"
8+
android:exported="true"
9+
android:launchMode="singleTop"
10+
android:theme="@style/LaunchTheme"
11+
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
12+
android:hardwareAccelerated="true"
13+
android:windowSoftInputMode="adjustResize">
14+
<!-- Specifies an Android theme to apply to this Activity as soon as
15+
the Android process has started. This theme is visible to the user
16+
while the Flutter UI initializes. After that, this theme continues
17+
to determine the Window background behind the Flutter UI. -->
18+
<meta-data
19+
android:name="io.flutter.embedding.android.NormalTheme"
20+
android:resource="@style/NormalTheme"
21+
/>
22+
<intent-filter>
23+
<action android:name="android.intent.action.MAIN"/>
24+
<category android:name="android.intent.category.LAUNCHER"/>
25+
</intent-filter>
26+
</activity>
27+
<!-- Don't delete the meta-data below.
28+
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
29+
<meta-data
30+
android:name="flutterEmbedding"
31+
android:value="2" />
32+
</application>
33+
</manifest>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.example.flutter_application_1
2+
3+
import io.flutter.embedding.android.FlutterActivity
4+
5+
class MainActivity: FlutterActivity() {
6+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- Modify this file to customize your launch splash screen -->
3+
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
4+
<item android:drawable="?android:colorBackground" />
5+
6+
<!-- You can insert your own image assets here -->
7+
<!-- <item>
8+
<bitmap
9+
android:gravity="center"
10+
android:src="@mipmap/launch_image" />
11+
</item> -->
12+
</layer-list>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- Modify this file to customize your launch splash screen -->
3+
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
4+
<item android:drawable="@android:color/white" />
5+
6+
<!-- You can insert your own image assets here -->
7+
<!-- <item>
8+
<bitmap
9+
android:gravity="center"
10+
android:src="@mipmap/launch_image" />
11+
</item> -->
12+
</layer-list>
544 Bytes
Loading

0 commit comments

Comments
 (0)