0 purchases
dart meteor
For Dart VM, Flutter iOS/Android (master branch)
For Flutter Web (web branch)
A Meteor DDP library for Dart/Flutter developers. #
This library makes a connection between the Meteor backend and the Flutter app simply. Design to work seamlessly with StreamBuilder and FutureBuilder.
Change on 3.0.0 #
BREAKING CHANGE. The meteor.collection('collectionName') streams are now snapshot.hasData == true and have an empty map at the beginning.
Change on 2.0.0 #
Passing arguments to meteor method is now optional. In version 1.x.x you did: meteor.call('your_method_name', [param1, param2]). Now in version 2.x.x, it will be meteor.call('your_method_name', args: [param1, param2]) or just meteor.call('your_method_name') if you don't want to pass any argument to your method.
Same as subscription. In version 1.x.x you did: meteor.subscribe('your_pub', [param1, param2]). Now in version 2.x.x, it will be meteor.subscribe('your_pub', args: [param1, param2]) or just meteor.subscribe('your_pub') if you don't want to pass any argument to make your subscription.
In version 1.x.x, you have to call meteor.prepareCollection('your_collection_name') before you can use it. Now in version 2.x.x, you don't have to prepare a collection. You now access the collection by calling collection method meteor.collection('messages').listen((value) { ... }).
DateTime are now directly support. You can pass a DateTime variable as a meteor method parameter and receive DateTime from the collections and methods.
Usage #
I have published a post on Medium showing how to handle connection status, user authentication, and subscriptions. Please check https://medium.com/@tanutapi/writing-flutter-mobile-application-with-meteor-backend-643d2c1947d0?source=friends_link&sk=52ce2fa2603934e7395e2d19dd54e06c
A simple usage example:
First, create an instance of MeteorClient in your app global scope so that it can be used anywhere in your project.
import 'package:flutter/material.dart';
import 'package:dart_meteor/dart_meteor.dart';
MeteorClient meteor = MeteorClient.connect(url: 'https://yourdomain.com');
void main() => runApp(MyApp());
copied to clipboard
In your StatefulWidget/StatelessWidget, thanks to rxdart, you can use FutuerBuilder or StreamBuilder to build your widget base on a response from meteor's DDP server.
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _methodResult = '';
void _callMethod() {
meteor.call('helloMethod').then((result) {
setState(() {
_methodResult = result.toString();
});
}).catchError((err) {
if (err is MeteorError) {
setState(() {
_methodResult = err.message;
});
}
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Package dart_meteor Example'),
),
body: Container(
padding: EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
StreamBuilder<DdpConnectionStatus>(
stream: meteor.status(),
builder: (context, snapshot) {
if (snapshot.hasData) {
if (snapshot.data.status ==
DdpConnectionStatusValues.connected) {
return RaisedButton(
child: Text('Disconnect'),
onPressed: () {
meteor.disconnect();
},
);
}
return RaisedButton(
child: Text('Connect'),
onPressed: () {
meteor.reconnect();
},
);
}
return Container();
},
),
StreamBuilder<DdpConnectionStatus>(
stream: meteor.status(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text('Meteor Status ${snapshot.data.toString()}');
}
return Text('Meteor Status: ---');
},
),
StreamBuilder(
stream: meteor.userId(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return RaisedButton(
child: Text('Logout'),
onPressed: () {
meteor.logout();
},
);
}
return RaisedButton(
child: Text('Login'),
onPressed: () {
meteor.loginWithPassword(
'yourusername', 'yourpassword');
},
);
}),
StreamBuilder(
stream: meteor.user(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data.toString());
}
return Text('User: ----');
},
),
RaisedButton(
child: Text('Method Call'),
onPressed: _callMethod,
),
Text(_methodResult),
],
),
),
),
);
}
}
copied to clipboard
Making a method call to your server #
Making a method call to your server returns a Future. You MUST handle catchError to prevent your app from crashing if something went wrong.
meteor.call('helloMethod').then((result) {
setState(() {
_methodResult = result.toString();
});
}).catchError((err) {
if (err is MeteorError) {
setState(() {
_methodResult = err.message;
});
}
});
copied to clipboard
You can also use it with a FutureBuilder.
FutureBuilder<int>(
future: meteor.call('sumMethod', args: [5, 10]),
builder: (context, snapshot) {
if (snapshot.hasData) {
// your snapshot.data should be 5 + 10 = 15
return Text('Answer is: ${snapshot.data}');
}
},
),
copied to clipboard
You can found an example project inside /example.
Collections & Subscriptions #
You can access your collections by calling collection('your_collection_name').
It will return a Stream which you can use it with your StreamBuilder or wherever you want. Through the returned Stream reference you can listen the updates of the collection.
meteor.collection('your_collections');
copied to clipboard
Which return a stream that backed by rxdart BehaviorSubject, a special StreamController that captures the latest item that has been added to the controller, and emits that as the first item to any new listener. You can use it as a simple Stream. To make collections available in Flutter app you might make a subscription to your server with:
class YourWidget extends StatefulWidget {
YourWidget() {}
@override
_YourWidgetState createState() => _YourWidgetState();
}
class _YourWidgetState extends State<YourWidget> {
SubscriptionHandler _subscriptionHandler;
@override
void initState() {
super.initState();
_subscriptionHandler = meteor.subscribe('your_pub', args: ['param_1', 'param_2']);
}
@override
void dispose() {
_subscriptionHandler.stop();
super.dispose();
}
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: meteor.collection('your_collection'),
builder:
(context, AsyncSnapshot<Map<String, dynamic>> snapshot) {
int docCount = 0;
if (snapshot.hasData) {
docCount = snapshot.data.length;
}
return Text('Total document count: $docCount');
},
);
}
}
copied to clipboard
The collection was return as a Map<String, dynamic>. The key is a document ._id and its value is the whole document.
Ex.
{
"DGbsysgxzSf7Cr8Jg": {
"_id": "DGbsysgxzSf7Cr8Jg",
field1: 0,
field2: "a",
field3: true,
field4: SomeDate
}
}
copied to clipboard
We did not provide some kind of minimongo. We believe that you can use reduce, map, and where with the collection and get the same result as you did with a query in minimongo meteor web client.
Don't want to access data via stream #
Getting the current data from stream is sometime complicated. Especially when you just want to get the latest value just for a condition checking. You can access the latest value from the collection, user, userId directly with meteor.collectionCurrentValue('your_collection_name'), meteor.userCurrentValue(), and meteor.userIdCurrentValue().
findOne with _id #
The best way to access the document if you have an id is
// Non-reactive
// Example of accessing an document by it's id
final id = 'DGbsysgxzSf7Cr8Jg';
final doc = meteor.collectionCurrentValue('your_collection_name')[id];
if (doc != null) {
// do something
}
// Non-reactive
// Example of accessing an user by userId
final userId = 'Sf7Cr8JgDGbsysgxz';
final user = meteor.collectionCurrentValue('users')[userId];
if (user != null) {
// do something
}
copied to clipboard
Features and bugs #
Please file feature requests and bugs at the issue tracker.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.