Hi all, what I am trying to do is to read and write from a MongoDB atlas cloud database from my Flutter application. I am trying to use Realm to do so (I was previously using the mongo_dart plugin which was much simpler but this doesn’t work for web apps). To do so, I downloaded and unzipped the Flutter flexible sync demo available here: https://github.com/realm/realm-dart-samples/tree/main/flutter_flexible_sync. After downloading this file, I just replaced my app ID and ran it. After running the app, I realized that I had a defined schema in mongoDB but pressing the buttons at the bottom of the screen did not write anything to the database. The app is successfully reading from the database but it cannot write to it. You’ll realize that I thought this was due to me not subscribing to it so I pasted (now commented out in the code below) some sample code I found on the Flutter realm package website to create a mutable subscription). I added print statements in the _createImportantTasks function to see if it was exiting somewhere in the middle of the function but it seemed to be working just fine and I don’t have errors in my debug console. All I want to do is to be able to read the “linkID” property from a Links Schema I would like to create by querying for it for a user with the specified “username” property (i.e. finding the linkID of user with the email jo@gmail.com). I also want to be able to insert new users into the Link collection (with a name string property, a linkID string property, and an email string property). How can I do this? Here’s the code I was trying out:
import 'dart:convert';
import 'dart:io';
import 'package:flutter/services.dart' show rootBundle;
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:realm/realm.dart';
import 'model.dart';
// part 'app.g.dart';
@RealmModel() // define a data model class named `_Car`.
class _Car {
late String make;
late String model;
int? kilometers = 500;
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final realmConfig = {
"config_version": 20210101,
"app_id": "teescanfire-jumnr",
"name": "flutter_flexible_sync",
"location": "DE-FF",
"deployment_model": "LOCAL"
};
String appId = "teescanfire-jumnr";
// String appId = realmConfig['app_id'];
MyApp.allTasksRealm = await createRealm(appId, CollectionType.allTasks);
MyApp.importantTasksRealm =
await createRealm(appId, CollectionType.importantTasks);
MyApp.normalTasksRealm = await createRealm(appId, CollectionType.normalTasks);
runApp(const MyApp());
}
enum CollectionType { allTasks, importantTasks, normalTasks }
Future<Realm> createRealm(String appId, CollectionType collectionType) async {
final appConfig = AppConfiguration(appId);
final app = App(appConfig);
final user = await app.logIn(Credentials.anonymous());
final flxConfig = Configuration.flexibleSync(user, [Task.schema],
path: await absolutePath("db_${collectionType.name}.realm"));
var realm = Realm(flxConfig);
print("Created local realm db at: ${realm.config.path}");
final RealmResults<Task> query;
if (collectionType == CollectionType.allTasks) {
query = realm.all<Task>();
} else {
query = realm.query<Task>(r'isImportant == $0',
[collectionType == CollectionType.importantTasks]);
}
realm.subscriptions.update((mutableSubscriptions) {
mutableSubscriptions.add(query);
});
await realm.subscriptions.waitForSynchronization();
await realm.syncSession.waitForDownload();
print("Syncronization completed for realm: ${realm.config.path}");
return realm;
}
Future<String> absolutePath(String fileName) async {
final appDocsDirectory = await getApplicationDocumentsDirectory();
final realmDirectory = '${appDocsDirectory.path}/mongodb-realm';
if (!Directory(realmDirectory).existsSync()) {
await Directory(realmDirectory).create(recursive: true);
}
return "$realmDirectory/$fileName";
}
class MyApp extends StatelessWidget {
static late Realm allTasksRealm;
static late Realm importantTasksRealm;
static late Realm normalTasksRealm;
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: const MyHomePage(title: 'Flutter Realm Flexible Sync'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _allTasksCount = MyApp.allTasksRealm.all<Task>().length;
int _importantTasksCount = MyApp.importantTasksRealm.all<Task>().length;
int _normalTasksCount = MyApp.normalTasksRealm.all<Task>().length;
void _createImportantTasks() async {
// print("going to try insert method I found on GitHub");
// MyApp.importantTasksRealm.subscriptions.update((mutableSubscriptions) {
// mutableSubscriptions.add(MyApp.importantTasksRealm.query<Task>(
// r'isCompleted == $0 AND isImportant == $1', [true, false]));
// });
// await MyApp.importantTasksRealm.subscriptions.waitForSynchronization();
// MyApp.normalTasksRealm.write(() {
// MyApp.importantTasksRealm
// .add(Task(ObjectId(), "Send an email", true, false));
// });
print("Starting to create an important task");
var importantTasks = MyApp.importantTasksRealm.all<Task>();
print("Starting to count an important task");
var allTasksCount = MyApp.allTasksRealm.all<Task>();
print("Starting to write important task");
MyApp.allTasksRealm.write(() {
MyApp.allTasksRealm.add(Task(ObjectId(),
"Important task ${importantTasks.length + 1}", false, true));
});
print("Waiting for upload");
await MyApp.allTasksRealm.syncSession.waitForUpload();
print("Waiting for sync");
await MyApp.importantTasksRealm.subscriptions.waitForSynchronization();
print("Setting State");
setState(() {
_importantTasksCount = importantTasks.length;
_allTasksCount = allTasksCount.length;
});
}
void _createNormalTasks() async {
var normalTasks = MyApp.normalTasksRealm.all<Task>();
var allTasksCount = MyApp.allTasksRealm.all<Task>();
MyApp.allTasksRealm.write(() {
MyApp.allTasksRealm.add(Task(
ObjectId(), "Normal task ${normalTasks.length + 1}", false, false));
});
await MyApp.allTasksRealm.syncSession.waitForUpload();
await MyApp.normalTasksRealm.subscriptions.waitForSynchronization();
setState(() {
_normalTasksCount = normalTasks.length;
_allTasksCount = allTasksCount.length;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('Important tasks count:',
style: TextStyle(fontWeight: FontWeight.bold)),
Text('$_importantTasksCount',
style: Theme.of(context).textTheme.headline4),
const Text('Normal tasks count:',
style: TextStyle(fontWeight: FontWeight.bold)),
Text('$_normalTasksCount',
style: Theme.of(context).textTheme.headline4),
const Text('All tasks count:',
style: TextStyle(fontWeight: FontWeight.bold)),
Text('$_allTasksCount',
style: Theme.of(context).textTheme.headline4),
],
),
),
floatingActionButton: Stack(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 0.0),
child: Align(
alignment: Alignment.bottomLeft,
child: FloatingActionButton(
onPressed: _createImportantTasks,
tooltip: 'High priority task',
child: const Icon(Icons.add),
)),
),
Padding(
padding: const EdgeInsets.only(right: 40.0),
child: Align(
alignment: Alignment.bottomRight,
child: FloatingActionButton(
onPressed: _createNormalTasks,
tooltip: 'Normal task',
child: const Icon(Icons.add),
)),
),
],
),
floatingActionButtonLocation: FloatingActionButtonLocation.startFloat);
}
}
// class _MyHomePageState extends State<MyHomePage> {
// int _allTasksCount = 0;
// int _importantTasksCount = 0;
// int _normalTasksCount = 0;
// @override
// void initState() {
// super.initState();
// _fetchTaskCounts();
// }
// void _fetchTaskCounts() {
// _allTasksCount = MyApp.allTasksRealm.all<Task>().length;
// _importantTasksCount = MyApp.importantTasksRealm.all<Task>().length;
// _normalTasksCount = MyApp.normalTasksRealm.all<Task>().length;
// }
// void _createTask(bool isImportant) async {
// MyApp.allTasksRealm.write(() {
// MyApp.allTasksRealm.add(
// Task(ObjectId(), "New task", false, isImportant),
// );
// });
// await MyApp.allTasksRealm.syncSession.waitForUpload();
// await MyApp.allTasksRealm.subscriptions.waitForSynchronization();
// setState(() {
// _fetchTaskCounts();
// });
// }
// void writeObjectToDatabase() async {}
// @override
// Widget build(BuildContext context) {
// return Scaffold(
// appBar: AppBar(
// title: Text(widget.title),
// ),
// body: Center(
// child: Column(
// mainAxisAlignment: MainAxisAlignment.center,
// children: <Widget>[
// const Text(
// 'Important tasks count:',
// style: TextStyle(fontWeight: FontWeight.bold),
// ),
// Text(
// '$_importantTasksCount',
// style: Theme.of(context).textTheme.headline4,
// ),
// const Text(
// 'Normal tasks count:',
// style: TextStyle(fontWeight: FontWeight.bold),
// ),
// Text(
// '$_normalTasksCount',
// style: Theme.of(context).textTheme.headline4,
// ),
// const Text(
// 'All tasks count:',
// style: TextStyle(fontWeight: FontWeight.bold),
// ),
// Text(
// '$_allTasksCount',
// style: Theme.of(context).textTheme.headline4,
// ),
// ],
// ),
// ),
// floatingActionButton: FloatingActionButton(
// onPressed: () => _createTask(true),
// tooltip: 'Create Task',
// child: const Icon(Icons.add),
// ),
// );
// }
// }
Here’s how my UI looks (I’d like to press on a button on the screen to write a new object to a specific collection):
Note: I’ve allowed anonymous access to my database, it’s in development mode, and I’ve allowed access from any IP