MongoDB is a popular NoSQL database known for its flexibility and scalability. Integrating MongoDB with a Flutter app can be a powerful combination. In this blog, we’ll explore how to connect MongoDB to a Flutter app using the realm
package.
Prerequisites
Before we begin, make sure you have the following prerequisites:
Flutter Installed: Ensure that you have Flutter and Dart set up on your development machine. You can download Flutter from here.
Server: MongoDB should be installed and running. You can download and install MongoDB from here.
MongoDB Database: Create a MongoDB database where your app data will be stored.
Setting Up the Flutter Project
Let’s create a new Flutter project or use an existing one.
- Add Dependencies:
In your pubspec.yaml
file, add the realm
package:
dependencies:
flutter:
sdk: flutter
realm: ^latest_version
Replace latest_version
with the actual version of realm
.
- Run
flutter pub get
to fetch and install the dependencies.
Step 1: Import the Package
In your Flutter project, import the realm
package in the Dart file where you intend to work with MongoDB.
import 'package:realm/realm.dart';
Step 2: Establish a Connection
To connent your flutter app to mongodb database you need to make project in mongodb cloud and create one project
If you don’t know how to create realm project in mongo db then follow below instruction.
Create account in mongodb cloud
Create a project
Click on your rightside of Altas logo there popup will open scroll down then you will see create new mongo db project
After creating mongo db project you will see this option
This will shown after click on create database option in your mongodb project
After creating database click on database and inside database click on collection then create a new own collection
Click on App services then you will get this option
Let’s start write a code how you connect app to mongo db
In this tutorial we will use provider for state management
- Create config.json to add your configuration
{
"appId": "write app id",
"appUrl": "https://realm.mongodb.com/groups/{delete this url and add your realm app url}",
"baseUrl": "https://realm.mongodb.com",
"clientApiBaseUrl": "https://ap-south-1.aws.realm.mongodb.com",
"dataApiBaseUrl": "https://ap-south-1.aws.data.mongodb-api.com",
"dataExplorerLink": "https://cloud.mongodb.com/links/ {delete this url and add your cloud app url} ",
"dataSourceName": "mongodb-atlas"
}
Create a schema.dart add code in below format
import 'package:realm/realm.dart';
part 'schemas.g.dart';
@RealmModel()
@MapTo('listing')
class _Listing {
@PrimaryKey()
@MapTo('_id')
late ObjectId id;
int? bathroomCount;
late String category;
late String country;
DateTime? createdAt;
String? description;
late List<_ListingFacilities> facilities;
int? guestCount;
String? hotelspecification;
late List<String> imageSrc;
late List<double> locationValue;
late String placename;
String? placenameCode;
late int price;
double? rating;
int? roomCount;
late String title;
ObjectId? userId;
}
@RealmModel(ObjectType.embeddedObject)
@MapTo('listing_facilities')
class _ListingFacilities {
String? fav;
String? icon;
}
@RealmModel()
@MapTo('place')
class _Place {
@PrimaryKey()
@MapTo('_id')
late ObjectId id;
late String category;
late String country;
DateTime? createdAt;
String? description;
late List<_PlaceFacilities> facilities;
late List<String> imageSrc;
late String location;
late List<double> locationValue;
late int price;
String? rating;
late String title;
}
@RealmModel(ObjectType.embeddedObject)
@MapTo('place_facilities')
class _PlaceFacilities {
String? fac;
String? icon;
}
@RealmModel()
@MapTo('userdata')
class _Userdata {
@PrimaryKey()
@MapTo('_id')
ObjectId? id;
@MapTo('owner_id')
late String ownerId;
String? country;
DateTime? createdAt;
late String email;
bool? emailVerified;
String? name;
late String password;
String? phonenumber;
DateTime? updatedAt;
// List<_Reservations> reservations = [];
}
@RealmModel()
@MapTo('allreservation')
class _AllReservations {
@PrimaryKey()
@MapTo('_id')
late ObjectId id;
DateTime? createdAt;
late DateTime enddate;
late ObjectId listingId;
late DateTime startDate;
late int totalprice;
late ObjectId userId;
}
dart run realm generate --clean
Run this command after creating schema.dart
Now you will see new file called schema.g.dart
Create app services and realm services
Write below code to create app services with login and signup
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:realm/realm.dart';
import 'package:travel_app/realm/realm_services.dart';
class AppServices with ChangeNotifier {
String id;
Uri baseUrl;
App app;
User? currentUser;
AppServices(this.id, this.baseUrl)
: app = App(AppConfiguration(id, baseUrl: baseUrl));
Future<Map<String, dynamic>> logInUserEmailPassword(
String email, String password, BuildContext context) async {
try {
await currentUser?.logOut();
User loggedInUser =
await app.logIn(Credentials.emailPassword(email, password));
if (!context.mounted) {
return {"success": false, "message": "Some error occurred!"};
}
final realmServices = Provider.of<RealmServices>(context, listen: false);
currentUser = loggedInUser;
realmServices.currentUser = loggedInUser;
notifyListeners();
return {"success": true, "message": "Login successfully!"};
} catch (e) {
return {"success": false, "message": "Some error occurred!"};
}
}
Future<Map<String, dynamic>> registerUserEmailPassword(
String email, String password, String name, BuildContext context) async {
try {
await currentUser?.logOut();
EmailPasswordAuthProvider authProvider = EmailPasswordAuthProvider(app);
await authProvider.registerUser(email, password);
User loggedInUser =
await app.logIn(Credentials.emailPassword(email, password));
if (!context.mounted) {
return {"success": false, "message": "Some error occurred!"};
}
final realmServices = Provider.of<RealmServices>(context, listen: false);
await realmServices.createUser(email, password, name, loggedInUser.id);
loggedInUser.logOut();
notifyListeners();
return {"success": true, "message": "User created successfully!"};
} catch (e) {
// if (e.runtimeType == RealmInvalidCredentialsException) {}else{}
return {"success": false, "message": "Some error occurred!"};
}
}
Future<void> logOut() async {
await currentUser?.logOut();
currentUser = null;
}
}
Create file called realm_service.dart
import 'package:travel_app/realm/schemas.dart';
import 'package:realm/realm.dart';
import 'package:flutter/material.dart';
class RealmServices with ChangeNotifier {
static const String queryAllName = "getAllItemsSubscription";
static const String queryMyItemsName = "getMyItemsSubscription";
bool offlineModeOn = false;
bool isWaiting = false;
late Realm realm;
User? currentUser;
App app;
RealmServices(this.app) {
if (app.currentUser != null || currentUser != app.currentUser) {
currentUser ??= app.currentUser;
realm = Realm(Configuration.flexibleSync(currentUser!, [
Userdata.schema,
Place.schema,
Listing.schema,
ListingFacilities.schema,
PlaceFacilities.schema,
AllReservations.schema
]));
if (realm.subscriptions.isEmpty) {
updateSubscriptions();
notifyListeners();
}
}
}
Future<void> updateSubscriptions() async {
realm.subscriptions.update((mutableSubscriptions) {
mutableSubscriptions.clear();
mutableSubscriptions.add(realm.all<Userdata>());
mutableSubscriptions.add(realm.all<Place>());
mutableSubscriptions.add(realm.all<Listing>());
mutableSubscriptions.add(realm.all<AllReservations>());
});
await realm.subscriptions.waitForSynchronization();
notifyListeners();
}
Future<void> sessionSwitch() async {
offlineModeOn = !offlineModeOn;
if (offlineModeOn) {
realm.syncSession.pause();
} else {
try {
isWaiting = true;
notifyListeners();
realm.syncSession.resume();
await updateSubscriptions();
} finally {
isWaiting = false;
}
}
notifyListeners();
}
Future<void> switchSubscription(bool value) async {
if (!offlineModeOn) {
try {
isWaiting = true;
notifyListeners();
await updateSubscriptions();
} finally {
isWaiting = false;
}
}
notifyListeners();
}
Future<void> createUser(
String email, String password, String name, String ownerId) async {
try {
final newItem = Userdata(
ObjectId(),
ownerId,
email,
password,
name: name,
createdAt: DateTime.now(),
updatedAt: DateTime.now(),
emailVerified: false,
);
realm.write<Userdata>(() => realm.add<Userdata>(newItem));
print("Hello");
} catch (e) {
print(e);
} finally {
notifyListeners();
}
}
Future<void> close() async {
if (currentUser != null) {
currentUser = null;
}
realm.close();
}
}
add below code in main.dart file
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:travel_app/screens/homescreen.dart';
import 'package:travel_app/screens/onboardingscreen.dart';
import 'package:travel_app/screens/onboardingslider.dart';
import 'package:travel_app/screens/splashscreen.dart';
import 'package:travel_app/themes/dark_theme.dart';
import 'package:travel_app/themes/light_theme.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:travel_app/realm/realm_services.dart';
import 'package:travel_app/realm/app_services.dart';
import 'dart:convert';
import 'package:realm/realm.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
Config realmConfig = await Config.getConfig('assets/config/atlasConfig.json');
final appConfig = AppConfiguration(realmConfig.appId);
final app = App(appConfig);
if (app.currentUser == null) {
try {
final anonCredentials = Credentials.anonymous();
await app.logIn(anonCredentials);
} catch (e) {
print(e);
}
}
runApp(MultiProvider(
providers: [
ChangeNotifierProvider<Config>(create: (_) => realmConfig),
ChangeNotifierProvider<AppServices>(
create: (_) => AppServices(realmConfig.appId, realmConfig.baseUrl)),
ChangeNotifierProxyProvider<AppServices, RealmServices?>(
// RealmServices can only be initialized only if the user is logged in.
create: (context) => null,
update: (BuildContext context, AppServices appServices,
RealmServices? realmServices) {
return RealmServices(appServices.app);
}),
],
builder: (context, child) {
return const MyApp();
},
));
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
final realmServices = Provider.of<RealmServices>(context);
return MaterialApp(
theme: lightTheme,
themeMode: ThemeMode.system,
darkTheme: lightTheme,
debugShowCheckedModeBanner: false,
home: realmServices.currentUser != null &&
realmServices.currentUser!.provider != AuthProviderType.anonymous
? const HomeScreen()
: const SplashScreen(),
// home: const LoginScreen(),
// home: const OnboardingScreen(),
);
}
}
class Config extends ChangeNotifier {
late String appId;
late String atlasUrl;
late Uri baseUrl;
Config._create(dynamic realmConfig) {
appId = realmConfig['appId'];
atlasUrl = realmConfig['dataExplorerLink'];
baseUrl = Uri.parse(realmConfig['baseUrl']);
}
static Future<Config> getConfig(String jsonConfigPath) async {
dynamic realmConfig =
json.decode(await rootBundle.loadString(jsonConfigPath));
var config = Config._create(realmConfig);
return config;
}
}
If you have any queries then check this repository