Meteor <IP_ADDRESS>
Meteor is an ultra-simple environment for building modern websites. What once took weeks, even with the best tools, now takes hours with Meteor.
The web was originally designed to work in the same way that mainframes worked in the 70s.  Whenever the user did anything, that server rerendered a whole new screen. This model served the Web well for over a decade. It gave rise to LAMP, Rails, Django, PHP.
But the best teams, with the biggest budgets and the longest schedules, now build applications in JavaScript that run on the client. These apps have stellar interfaces. They don't reload pages. They are reactive: changes from any client immediately appear on everyone's screen.
They've built them the hard way. Meteor makes it an order of magnitude simpler, and a lot more fun. You can build a complete application in a weekend, or a sufficiently caffeinated hackathon. No longer do you need to provision server resources, or deploy API endpoints in the cloud, or manage a database, or wrangle an ORM layer, or swap back and forth between JavaScript and Ruby, or broadcast data invalidations to clients.
Meteor is a work in progress, but we hope it shows the direction of our thinking. We'd love to hear your feedback.
Quick start!
The following works on all supported platforms.
Install Meteor:
$ curl https://install.meteor.com | /bin/sh
Create a project:
$ meteor create myapp
Run it locally:
$ cd myapp $ meteor => Meteor server running on: http://localhost:3000/
Unleash it on the world (on a free server we provide):
$ meteor deploy myapp.meteor.com
Seven Principles of Meteor
- Data on the Wire. Don't send HTML over the network. Send data and let the client decide how to render it.
- One Language. Write both the client and the server parts of your interface in JavaScript.
- Database Everywhere. Use the same transparent API to access your database from the client or the server.
- Latency Compensation. On the client, use prefetching and model simulation to make it look like you have a zero-latency connection to the database.
Full Stack Reactivity. Make realtime the default. All layers, from database to template, should make an event-driven interface available.
Embrace the Ecosystem. Meteor is open source and integrates, rather than replaces, existing open source tools and frameworks.
- Simplicity Equals Productivity. The best way to make something seem simple is to have it actually be simple. Accomplish this through clean, classically beautiful APIs.
Developer Resources
If anything in Meteor catches your interest, we hope you'll get involved with the project!
- Stack Overflow
- The best place to ask (and answer!) technical questions is on Stack
Overflow. Be sure to add
the
meteor
tag to your question. - Mailing lists
-
We have two mailing lists for Meteor.
is for general questions, requests for help, and new project<EMAIL_ADDRESS>is for discussing Meteor internals and proposed<EMAIL_ADDRESS>- IRC
#meteor
onirc.freenode.net
. The developers hang out here and will answer your questions whenever they can.- GitHub
- The code is on GitHub. The best way to send a patch is with a GitHub pull request, and the best way to file a bug is in the GitHub bug tracker, after reading our guide to filing bug reports. If the issue contains sensitive information or raises a security concern, email
security
@
meteor
.
com
instead, which will page the security team.
Concepts
We've written our fair share of single-page JavaScript applications by hand. Writing an entire application in one language (JavaScript) with one data format (JSON) is a real joy. Meteor is everything we wanted when writing those apps.What is Meteor?
Meteor is two things:
A library of packages: pre-written, self-contained modules that you might need in your app.
There are about a dozen core Meteor packages that most any app will use (for examplewebapp
, which handles incoming HTTP connections, andtemplating
, which lets you make HTML templates that automatically update live as data changes). Then there are optional packages likeemail
, which lets your app send emails, or the Meteor Accounts series (account-password
,accounts-facebook
,accounts-ui
, and others) which provide a full-featured user account system that you can drop right into your app. And beyond these "official" packages, there are hundreds of community-written packages in Atmosphere, one of which might do just what you need.A command-line tool called
meteor
.
meteor
is a build tool analogous tomake
,rake
, or the non-visual parts of Visual Studio. It gathers up all of the source files and assets in your application, carries out any necessary build steps (such as compiling CoffeeScript, minifying CSS, building npm modules, or generating source maps), fetches the packages used by your app, and outputs a standalone, ready-to-run application bundle. In development mode it can do all of this interactively, so that whenever you change a file you immediately see the changes in your browser. It's super easy to use out of the box, but it's also extensible: you can add support for new languages and compilers by adding build plugin packages to your app.
The key idea in the Meteor package system is that everything should work identically in the browser and on the server (wherever it makes sense, of course: browsers can't send email and servers can't capture mouse events). Our whole ecosystem has been built from the ground up to support this.
meteor
cannot yet fetch packages from Atmosphere. If you are using
Atmosphere packages you should take a look at
Meteorite, a tool that will
help you download and manage your Atmosphere packages.
In Meteor 1.0, the meteor
build tool will have full support for
Atmosphere.
Structuring your application
A Meteor application is a mix of JavaScript that runs inside a client web browser, JavaScript that runs on the Meteor server inside a Node.js container, and all the supporting HTML fragments, CSS rules, and static assets. Meteor automates the packaging and transmission of these different components. And, it is quite flexible about how you choose to structure those components in your file tree.
The only server assets are JavaScript and files in the private
subdirectory.
Meteor gathers all your JavaScript
files, excluding anything under the client
, public
, and private
subdirectories, and loads them into a Node.js
server instance inside a fiber. In Meteor, your server code runs in
a single thread per request, not in the asynchronous callback style
typical of Node. We find the linear execution model a better fit for
the typical server code in a Meteor application.
Meteor gathers any files under the private
subdirectory and makes the contents
of these files available to server code via the Assets
API. The
private
subdirectory is the place for any files that should be accessible to
server code but not served to the client, like private data files.
There are more assets to consider on the client side. Meteor
gathers all JavaScript files in your tree, with the exception of
the server
, public
, and private
subdirectories, for the
client. It minifies this bundle and serves it to each new client.
You're free to use a single JavaScript file for your entire application, or
create a nested tree of separate files, or anything in between.
Some JavaScript libraries only work when placed in the
client/compatibility
subdirectory. Files in this directory are
executed without being wrapped in a new variable scope. This means
that each top-level var
defines a global variable. In addition,
these files are executed before other client-side JavaScript files.
Files outside the client
, server
and tests
subdirectories are loaded on
both the client and the server! That's the place for model definitions and
other functions. Meteor provides the variables isClient
and
isServer
so that your code can alter its behavior depending
on whether it's running on the client or the server. (Files in directories named
tests
are not loaded anywhere.)
Any sensitive code that you don't want served to the client, such as code
containing passwords or authentication mechanisms, should be
kept in the server
directory.
CSS files are gathered together as well: the client will get a bundle with all
the CSS in your tree (excluding the server
,
public
, and private
subdirectories).
In development mode, JavaScript and CSS files are sent individually to make debugging easier.
HTML files in a Meteor application are treated quite a bit differently
from a server-side framework. Meteor scans all the HTML files in your
directory for three top-level elements: <head>
, <body>
, and
<template>
. The head and body sections are separately concatenated
into a single head and body, which are transmitted to the client on
initial page load.
Template sections, on the other hand, are converted into JavaScript
functions, available under the Template
namespace. It's
a really convenient way to ship HTML templates to the client.
See the templates section for more.
Lastly, the Meteor server will serve any files under the public
directory, just like in a Rails or Django project. This is the place
for images, favicon.ico
, robots.txt
, and anything else.
It is best to write your application in such a way that it is insensitive to the order in which files are loaded, for example by using Meteor.startup, or by moving load order sensitive code into packages, which can explicitly control both the load order of their contents and their load order with respect to other packages. However sometimes load order dependencies in your application are unavoidable. The JavaScript and CSS files in an application are loaded according to these rules:
Files in the
lib
directory at the root of your application are loaded first.Files that match
main.*
are loaded after everything else.Files in subdirectories are loaded before files in parent directories, so that files in the deepest subdirectory are loaded first (after
lib
), and files in the root directory are loaded last (other thanmain.*
).Within a directory, files are loaded in alphabetical order by filename.
These rules stack, so that within lib
, for example, files are still
loaded in alphabetical order; and if there are multiple files named
main.js
, the ones in subdirectories are loaded earlier.
Data and security
Meteor makes writing distributed client code as simple as talking to a local database. It's a clean, simple, and secure approach that obviates the need to implement individual RPC endpoints, manually cache data on the client to avoid slow roundtrips to the server, and carefully orchestrate invalidation messages to every client as data changes.
In Meteor, the client and server share the same database API. The same exact application code — like validators and computed properties — can often run in both places. But while code running on the server has direct access to the database, code running on the client does not. This distinction is the basis for Meteor's data security model.
By default, a new Meteor app includes the autopublish
and insecure
packages, which together mimic the effect of each client having full
read/write access to the server's database. These are useful
prototyping tools, but typically not appropriate for production
applications. When you're ready, just remove the packages.
Every Meteor client includes an in-memory database cache. To manage the client cache, the server publishes sets of JSON documents, and the client subscribes to those sets. As documents in a set change, the server patches each client's cache.
Today most Meteor apps use MongoDB as their database because it is the
best supported, though support for other databases is coming in the
future. The
Meteor.Collection
class
is used to declare Mongo collections and to manipulate them. Thanks to
minimongo
, Meteor's client-side Mongo emulator, Meteor.Collection
can be used from both client and server code.
// declare collections
// this code should be included in both the client and the server
Rooms = new Meteor.Collection("rooms");
Messages = new Meteor.Collection("messages");
Parties = new Meteor.Collection("parties");
// server: populate collections with some initial documents
Rooms.insert({name: "Conference Room A"});
var myRooms = Rooms.find({}).fetch();
Messages.insert({text: "Hello world", room: myRooms[0]._id});
Parties.insert({name: "Super Bowl Party"});
Each document set is defined by a publish function on the server. The publish function runs each time a new client subscribes to a document set. The data in a document set can come from anywhere, but the common case is to publish a database query.
// server: publish all room documents
Meteor.publish("all-rooms", function () {
return Rooms.find(); // everything
});
// server: publish all messages for a given room
Meteor.publish("messages", function (roomId) {
check(roomId, String);
return Messages.find({room: roomId});
});
// server: publish the set of parties the logged-in user can see.
Meteor.publish("parties", function () {
return Parties.find({$or: [{"public": true},
{invited: this.userId},
{owner: this.userId}]});
});
Publish functions can provide different results to each client. In the
last example, a logged in user can only see Party
documents that
are public, that the user owns, or that the user has been invited to.
Once subscribed, the client uses its cache as a fast local database, dramatically simplifying client code. Reads never require a costly round trip to the server. And they're limited to the contents of the cache: a query for every document in a collection on a client will only return documents the server is publishing to that client.
// client: start a parties subscription
Meteor.subscribe("parties");
// client: return array of Parties this client can read
return Parties.find().fetch(); // synchronous!
Sophisticated clients can turn subscriptions on and off to control how much data is kept in the cache and manage network traffic. When a subscription is turned off, all its documents are removed from the cache unless the same document is also provided by another active subscription.
When the client changes one or more documents, it sends a message to the server requesting the change. The server checks the proposed change against a set of allow/deny rules you write as JavaScript functions. The server only accepts the change if all the rules pass.
// server: don't allow client to insert a party
Parties.allow({
insert: function (userId, party) {
return false;
}
});
// client: this will fail
var party = { ... };
Parties.insert(party);
If the server accepts the change, it applies the change to the database and automatically propagates the change to other clients subscribed to the affected documents. If not, the update fails, the server's database remains untouched, and no other client sees the update.
Meteor has a cute trick, though. When a client issues a write to the server, it also updates its local cache immediately, without waiting for the server's response. This means the screen will redraw right away. If the server accepted the update — what ought to happen most of the time in a properly behaving client — then the client got a jump on the change and didn't have to wait for the round trip to update its own screen. If the server rejects the change, Meteor patches up the client's cache with the server's result.
Putting it all together, these techniques accomplish latency compensation. Clients hold a fresh copy of the data they need, and never need to wait for a roundtrip to the server. And when clients modify data, those modifications can run locally without waiting for the confirmation from the server, while still giving the server final say over the requested change.
The current release of Meteor supports MongoDB, the popular document database, and the examples in this section use the MongoDB API. Future releases will include support for other databases.
Authentication and user accounts
Meteor includes Meteor Accounts, a state-of-the-art
authentication system. It features secure password login using the
Secure Remote Password
protocol,
and integration with external services including Facebook, GitHub,
Google, Meetup, Twitter, and Weibo. Meteor Accounts defines a
Meteor.users
collection where developers can store
application-specific user data.
Meteor also includes pre-built forms for common tasks like login, signup,
password change, and password reset emails. You can add Accounts
UI to your app with just one line of code. The accounts-ui
package even provides a configuration wizard that walks you through the steps to
set up the external login services you're using in your app.
Input validation
Meteor allows your methods and publish functions to take arguments of any JSON type. (In fact, Meteor's wire protocol supports EJSON, an extension of JSON which also supports other common types like dates and binary buffers.) JavaScript's dynamic typing means you don't need to declare precise types of every variable in your app, but it's usually helpful to ensure that the arguments that clients are passing to your methods and publish functions are of the type that you expect.
Meteor provides a lightweight library for checking that arguments and
other values are the type you expect them to be. Simply start your functions
with statements like check(username, String)
or
check(office, {building: String, room: Number})
. The check
call will
throw an error if its argument is of an unexpected type.
Meteor also provides an easy way to make sure that all of your methods
and publish functions validate all of their arguments. Just run
meteor add audit-argument-checks
and any
method or publish function which skips check
ing any of its arguments will fail
with an exception.
Reactivity
Meteor embraces the concept of reactive programming. This means that you can write your code in a simple imperative style, and the result will be automatically recalculated whenever data changes that your code depends on.
Deps.autorun(function () {
Meteor.subscribe("messages", Session.get("currentRoomId"));
});
This example (taken from a chat room client) sets up a data
subscription based on the session variable currentRoomId
.
If the value of Session.get("currentRoomId")
changes for any reason, the
function will be automatically re-run, setting up a new subscription that
replaces the old one.
This automatic recomputation is achieved by a cooperation between
Session
and Deps.autorun
. Deps.autorun
performs an arbitrary "reactive
computation" inside of which data dependencies are tracked, and it
will re-run its function argument as necessary. Data providers like
Session
, on the other hand, make note of the computation they are
called from and what data was requested, and they are prepared to send
an invalidation signal to the computation when the data changes.
This simple pattern (reactive computation + reactive data source) has wide applicability. Above, the programmer is saved from writing unsubscribe/resubscribe calls and making sure they are called at the right time. In general, Meteor can eliminate whole classes of data propagation code which would otherwise clog up your application with error-prone logic.
These Meteor functions run your code as a reactive computation:
And the reactive data sources that can trigger changes are:
Session
variables- Database queries on Collections
Meteor.status
- The
ready()
method on a subscription handle Meteor.user
Meteor.userId
Meteor.loggingIn
In addition, the following functions which return an object with a
stop
method, if called from a reactive computation, are stopped when
the computation is rerun or stopped:
Deps.autorun
(nested)Meteor.subscribe
observe()
andobserveChanges()
on cursors
Meteor's
implementation
is a package called Deps
that is fairly short and straightforward.
You can use it yourself to implement new reactive data sources.
Live HTML
HTML templating is central to web applications. With Meteor's live page update technology, you can render your HTML reactively, meaning that it will update automatically to track changes in the data used to generate it.
This optional feature works with any HTML templating library, or even with HTML you generate manually from JavaScript. Here's an example:
var fragment = Meteor.render(
function () {
var name = Session.get("name") || "Anonymous";
return "<div>Hello, " + name + "</div>";
});
document.body.appendChild(fragment);
Session.set("name", "Bob"); // page updates automatically!
Meteor.render
takes a rendering function, that is, a
function that returns some HTML as a string. It returns an auto-updating
DocumentFragment
. When there is a change to data used by the rendering
function, it is re-run. The DOM nodes in the DocumentFragment
then
update themselves in-place, no matter where they were inserted on the
page. It's completely automatic. Meteor.render
uses
a reactive computation to discover what data is used by the
rendering function.
Most of the time, though, you won't call these functions directly
— you'll just use your favorite templating package, such as
Handlebars or Jade. The render
and renderList
functions are intended
for people that are implementing new templating systems.
Meteor normally batches up any needed updates and executes them only
when your code isn't running. That way, you can be sure that the DOM
won't change out from underneath you. Sometimes you want the opposite
behavior. For example, if you've just inserted a record in the
database, you might want to force the DOM to update so you can find
the new elements using a library like jQuery. In that case, call
Deps.flush
to bring the DOM up to date
immediately.
When live-updating DOM elements are taken off the screen, they are automatically
cleaned up — their callbacks are torn down, any associated database
queries are stopped, and they stop updating. For this reason, you never have to
worry about the zombie
templates
that plague hand-written update logic. To protect your elements from cleanup,
just make sure that they are on-screen before your code returns to the event loop,
or before any call you make to Deps.flush
.
Another thorny problem in hand-written applications is element
preservation. Suppose the user is typing text into an <input>
element, and then the area of the page that includes that element is
redrawn. The user could be in for a bumpy ride, as the focus, the
cursor position, the partially entered text, and the accented
character input state will be lost when the <input>
is recreated.
This is another problem that Meteor solves for you. You can specify
elements to preserve when templates are re-rendered with the
preserve
directive on the template. Meteor will
preserve these elements even when their enclosing template is
rerendered, but will still update their children and copy over any
attribute changes.
Templates
Meteor makes it easy to use your favorite HTML templating language, such as Handlebars or Jade, along with Meteor's live page update technology. Just write your template as you normally would, and Meteor will take care of making it update in realtime.
To use this feature, create a file in your project with the .html
extension. In the file, make a <template>
tag and give it a
name
attribute. Put the template contents inside the tag. Meteor
will precompile the template, ship it down to the client, and make it
available as a function on the global Template
object.
Today, the only templating system that has been packaged for Meteor is Handlebars. Let us know what templating systems you'd like to use with Meteor. Meanwhile, see the Handlebars documentation and Meteor Handlebars extensions.
A template with a name
of hello
is rendered by calling the
function Template.hello
, passing any data for the template:
<template name="hello">
<div class="greeting">Hello there, {{first}} {{last}}!</div>
</template>
// in the JavaScript console
> Template.hello({first: "Alyssa", last: "Hacker"});
=> "<div class="greeting">Hello there, Alyssa Hacker!</div>"
This returns a string. To use the template along with the Live
HTML
system, and get DOM elements that update
automatically in place, use Meteor.render
:
Meteor.render(function () {
return Template.hello({first: "Alyssa", last: "Hacker"});
})
=> automatically updating DOM elements
The easiest way to get data into templates is by defining helper
functions in JavaScript. Just add the helper functions directly on the
Template.[template name]
object. For example, in this template:
<template name="players">
{{#each topScorers}}
<div>{{name}}</div>
{{/each}}
</template>
instead of passing in topScorers
as data when we call the
template function, we could define a function on Template.players
:
Template.players.topScorers = function () {
return Users.find({score: {$gt: 100}}, {sort: {score: -1}});
};
In this case, the data is coming from a database query. When the
database cursor is passed to #each
, it will wire up all of the
machinery to efficiently add and move DOM nodes as new results enter
the query.
Helpers can take arguments, and they receive the current template data
in this
:
// in a JavaScript file
Template.players.leagueIs = function (league) {
return this.league === league;
};
<template name="players">
{{#each topScorers}}
{{#if leagueIs "junior"}}
<div>Junior: {{name}}</div>
{{/if}}
{{#if leagueIs "senior"}}
<div>Senior: {{name}}</div>
{{/if}}
{{/each}}
</template>
Handlebars note: {{#if leagueIs "junior"}}
is
allowed because of a Meteor extension that allows nesting a helper
in a block helper. (Both if
and leagueIs
are
technically helpers, and stock Handlebars would not invoke
leagueIs
here.)
Helpers can also be used to pass in constant data.
// Works fine with {{#each sections}}
Template.report.sections = ["Situation", "Complication", "Resolution"];
Finally, you can use an events
declaration on a template function to set up a
table of event handlers. The format is documented at Event
Maps. The this
argument to the event handler will be
the data context of the element that triggered the event.
<template name="scores">
{{#each player}}
{{> playerScore}}
{{/each}}
</template>
<template name="playerScore">
<div>{{name}}: {{score}}
<span class="givePoints">Give points</span>
</div>
</template>
Template.playerScore.events({
'click .givePoints': function () {
Users.update(this._id, {$inc: {score: 2}});
}
});
Putting it all together, here's an example of how you can inject arbitrary data into your templates, and have them update automatically whenever that data changes. See Live HTML for further discussion.
<template name="forecast">
<div>It'll be {{prediction}} tonight</div>
</template>
// JavaScript: reactive helper function
Template.forecast.prediction = function () {
return Session.get("weather");
};
> Session.set("weather", "cloudy");
> document.body.appendChild(Meteor.render(Template.forecast));
In DOM: <div>It'll be cloudy tonight</div>
> Session.set("weather", "cool and dry");
In DOM: <div>It'll be cool and dry tonight</div>
Using packages
All of the functionality you've read about so far is implemented as
standard Meteor packages. This is possible thanks to Meteor's
unusually powerful package and build system. The same packages work in
the browser and on the server, and packages can contain plugins that
extend the build process, such as coffeescript
(CoffeeScript
compilation) or templating
(compiling HTML templates).
You can see a list of available packages
with meteor list
, add packages to your project
with meteor add
, and remove them
with meteor remove
.
By default all apps include the standard-app-packages
package. This
automatically pulls in the packages that make up the core Meteor
stack. To keep things simple, these core packages are also hidden in
the output for meteor list
, but you can read the
source code of standard-app-packages
to see what they are (as Meteor is pre-1.0, they may change from release to
release). If you want to build your own custom stack, just remove
standard-app-packages
from your app and add back in whichever of the standard
packages you want to keep.
In addition to the packages in the official Meteor release being used
by your app, meteor list
and meteor add
also search the packages
directory at the top of your app. If you've downloaded an unofficial
package from Atmosphere you should unpack it into that directory (the
unofficial Meteorite tool
streamlines this process). You can also use the packages
directory
to break your app into subpackages for your convenience — if you
are willing to brave the fact that the Meteor package format is not
documented yet and will change significantly before Meteor 1.0. See
Writing Packages.
Namespacing
Meteor's namespacing support makes it easy to write large applications in JavaScript. Each package that you use in your app exists in its own separate namespace, meaning that it sees only its own global variables and any variables provided by the packages that it specifically uses. Here's how it works.
When you declare a top-level variable, you have a choice. You can make the variable File Scope or Package Scope.
// File Scope. This variable will be visible only inside this
// one file. Other files in this app or package won't see it.
var alicePerson = {name: "alice"};
// Package Scope. This variable is visible to every file inside
// of this package or app. The difference is that 'var' is
// omitted.
bobPerson = {name: "bob"};
Notice that this is just the normal JavaScript syntax for declaring a variable that is local or global. Meteor scans your source code for global variable assignments and generates a wrapper that makes sure that your globals don't escape their appropriate namespace.
In addition to File Scope and Package Scope, there are also
Exports. An export is a variable that a package makes available to you
when you use it. For example, the email
package exports the Email
variable. If your app uses the email
package (and only if it uses
the email
package!) then your app can see Email
and you can call
Email.send
. Most packages have only one export, but some packages
might have two or three (for example, a package that provides several
classes that work together).
You see only the exports of the packages that you use directly. If you use package A, and package A uses package B, then you only see package A's exports. Package B's exports don't "leak" into your namespace just because you used package A. This keeps each namespace nice and tidy. Each app or package only sees their own globals plus the APIs of the packages that they specifically asked for.
When debugging your app, your browser's JavaScript console behaves as if it were attached to your app's namespace. You see your app's globals and the exports of the packages that your app uses directly. You don't see the variables from inside those packages, and you don't see the exports of your transitive dependencies (packages that aren't used directly by your app, but that are used by packages that are used by your app).
If you want to look inside packages from inside your in-browser debugger, you've got two options:
Set a breakpoint inside package code. While stopped on that breakpoint, the console will be in the package's namespace. You'll see the package's package-scope variables, imports, and also any file-scope variables for the file you're stopped in.
If a package
foo
is included in your app, regardless of whether your app uses it directly, its exports are available inPackage.foo
. For example, if theemail
package is loaded, then you can accessPackage.email.Email.send
even from namespaces that don't use theemail
package directly.
When declaring functions, keep in mind that function x () {}
is just
shorthard for var x = function () {}
in JavaScript. Consider these
examples:
// This is the same as 'var x = function () ...'. So x() is
// file-scope and can be called only from within this one file.
function x () { ... }
// No 'var', so x() is package-scope and can be called from
// any file inside this app or package.
x = function () { ... }
Technically speaking, globals in an app (as opposed to in a package) are actually true globals. They can't be captured in a scope that is private to the app code, because that would mean that they wouldn't be visible in the console during debugging! This means that app globals actually end up being visible in packages. That should never be a problem for properly written package code (since the app globals will still be properly shadowed by declarations in the packages). You certainly shouldn't depend on this quirk, and in the future Meteor may check for it and throw an error if you do.
Deploying
Meteor is a full application server. We include everything you need to deploy your application on the internet: you just provide the JavaScript, HTML, and CSS.
Running on Meteor's infrastructure
The easiest way to deploy your application is to use meteor
deploy
. We provide it because it's what, personally, we've always
wanted: an easy way to take an app idea, flesh it out over a weekend,
and put it out there for the world to use, with nothing getting in the
way of creativity.
$ meteor deploy myapp.meteor.com
Your application is now available at myapp.meteor.com. If this is the first time deploying to this hostname, Meteor creates a fresh empty database for your application. If you want to deploy an update, Meteor will preserve the existing data and just refresh the code.
You can also deploy to your own domain. Just set up the hostname you
want to use as a CNAME to origin.meteor.com
,
then deploy to that name.
$ meteor deploy www.myapp.com
We provide this as a free service so you can try Meteor. It is also helpful for quickly putting up internal betas, demos, and so on.
Running on your own infrastructure
You can also run your application on your own infrastructure, or any other hosting provider like Heroku.
To get started, run
$ meteor bundle myapp.tgz
This command will generate a fully-contained Node.js application in the form of a tarball. To run this application, you need to provide Node.js 0.8 and a MongoDB server. (The current release of Meteor has been tested with Node 0.8.24.) You can then run the application by invoking node, specifying the HTTP port for the application to listen on, and the MongoDB endpoint. If you don't already have a MongoDB server, we can recommend our friends at MongoHQ.
$ PORT=3000 MONGO_URL=mongodb://localhost:27017/myapp node bundle/main.js
Other packages may require other environment variables (for example, the email
package requires a MAIL_URL
environment variable).
For now, bundles will only run on the platform that the bundle was
created on. To run on a different platform, you'll need to rebuild
the native packages included in the bundle. To do that, make sure you
have npm
available, and run the following:
$ cd bundle/programs/server/node_modules
$ rm -r fibers
$ npm install<EMAIL_ADDRESS>Writing packages
The Meteor package format isn't officially documented and will change before Meteor 1.0. But that hasn't stopped people like you from creating hundreds of packages by reading the source code of existing packages and following the model.  Look in thepackages
directory of the Meteor source tree for examplepackage.js
files. The format and name of thepackage.js
file will change significantly before Meteor 1.0, but the functionality will be basically the same even though the syntax is different, so it will be easy to port your code.Packages explicitly list all of their source files using
api.add_files
, and the files are loaded exactly in the order specified. (This is different from apps, where Meteor scans a directory tree to find the source files.) Don't forget to include any build plugin packages (such ascoffeescript
or, if using HTML templates,templating
) that you require.Exporting a symbol from your package (see Namespacing) is accomplished with an
api.export
call from inside youron_use
handler.An esoteric point about exports: they are not lvalues. You can't set an exported variable to a new value after exporting it. If you export
a = {name: 'alice'}
then you can changea.name
anytime you want, but if after startup you seta
to a whole new object then the packages that importa
won't see the change. Since your exports are most always objects or functions, this is hardly ever an issue.Packages can use npm modules. Use
Npm.depends
in yourpackage.js
to list the npm modules that you need and the specific versions that you want to use. Then useNpm.require
inside your package to pull in the modules when you need them. Meteor strives to have 100% repeatable builds so that everyone on your team is always running the same code, and that's why you must explicitly lock your npm dependencies to specific versions. Behind the scenes, Meteor will usenpm shrinkwrap
to also lock down the versions of the transitive dependencies of all of the npm modules that you use.Whenever your package changes, Meteor will rebuild it (compiling non-JavaScript source files, fetching npm dependencies, constructing namespace wrappers, and so on). The built package will be cached and rebuilt only when a source file changes (tracked by SHA1) or when other dependencies such as build plugins change. To force a rebuild you can use the undocumented command
meteor rebuild-all
, but this should never be necessary (if it is, please send a bug report!).Build plugins are created with
_transitional_registerBuildPlugin
, an API that is very much in flux. See thecoffeescript
package for an example. Build plugins are fully-fledged Meteor programs in their own right and have their own namespace, package dependencies, source files and npm requirements. The oldregister_extension
API is deprecated and should not be used as it will prevent your package from being cached, slowing down builds.It is possible to create weak dependencies between packages. If package A has a weak dependency on package B, it means that including A in an app does not force B to be included too — but, if B is included, say by the app developer or by another package, then B will load before A. You can use this to make packages that optionally integrate with or enhance other packages if those packages are present. To create a weak dependency, pass
{weak: true}
as the third argument toapi.use
. When you weakly depend on a package you don't see its exports. You can detect if the possibly-present weakly-depended-on package is there by seeing ifPackage.foo
exists, and get its exports from the same place.It is also possible to create unordered dependencies by passing
{unordered: true}
. An unordered dependency is the exact opposite of a weak dependency. If A has an unordered dependency on B, then including A forces B to be included as well, but doesn't require B to load before A. This is occasionally useful for resolving circular dependencies.The build system also supports package implication. If package A implies package B, then it means that when someone depends on package A, it's as if they also depended on package B as well. In particular, they get B's exports. This is done with
api.imply
and can be used to create umbrella packages such asstandard-app-packages
that are a shortcut for pulling in a set of packages, or it can be helpful in factoring common code out of a set of packages as withaccounts-base
.The build system understands the idea of native code and has a system of architecture names to ensure that packages that are specific to one architecture aren't run on the wrong architecture. For example, if you include an npm module that has a native extension, your built Meteor package will be specific to your machine architecture, but if not your built Meteor package will be portable.
The Meteor API
Your JavaScript code can run in two environments: the client (browser), and the server (a Node.js container on a server). For each function in this API reference, we'll indicate if the function is available just on the client, just on the server, or Anywhere.
Meteor Core
Meteor.isClient Anywhere
Boolean variable. True if running in client environment.
Meteor.isServer Anywhere
Boolean variable. True if running in server environment.
Meteor.isServer
can be used to limit where code runs, but it does not
prevent code from being sent to the client. Any sensitive code that you
don't want served to the client, such as code containing passwords or
authentication mechanisms, should be kept in the server
directory.
Meteor.startup(func) Anywhere
Run code when a client or a server starts.
Arguments
- func Function
A function to run on startup.
On a server, the function will run as soon as the server process is finished starting. On a client, the function will run as soon as the DOM is ready.
The startup
callbacks are called in the same order as the calls to
Meteor.startup
were made.
On a client, startup
callbacks from packages will be called
first, followed by <body>
templates from your .html
files,
followed by your application code.
// On server startup, if the database is empty, create some initial data.
if (Meteor.isServer) {
Meteor.startup(function () {
if (Rooms.find().count() === 0) {
Rooms.insert({name: "Initial room"});
}
});
}
Meteor.absoluteUrl([path], [options]) Anywhere
Generate an absolute URL pointing to the application. The server reads from the ROOT_URL
environment variable to determine where it is running. This is taken care of automatically for apps deployed with meteor deploy
, but must be provided when using meteor bundle
.
Arguments
- path String
A path to append to the root URL. Do not include a leading "
/
".
Options
- secure Boolean
Create an HTTPS URL.
- replaceLocalhost Boolean
Replace localhost with <IP_ADDRESS>. Useful for services that don't recognize localhost as a domain name.
- rootUrl String
Override the default ROOT_URL from the server environment. For example: "
http://foo.example.com
"
Meteor.settings Anywhere
Meteor.settings
contains any deployment-specific options that were provided using the --settings
option for meteor run
or meteor deploy
. If you provide the --settings
option, Meteor.settings
will be the JSON object in the file you specify. Otherwise, Meteor.settings
will be an empty object. If the object contains a key named public
, then Meteor.settings.public
will also be available on the client.
Meteor.release Anywhere
Meteor.release
is a string containing the name of the release with which the project was built (for example, "<IP_ADDRESS>"
). It is undefined
if the project was built using a git checkout of Meteor.
Publish and subscribe
These functions control how Meteor servers publish sets of records and how clients can subscribe to those sets.
Meteor.publish(name, func) Server
Publish a record set.
Arguments
- name String
Name of the attribute set. If
null
, the set has no name, and the record set is automatically sent to all connected clients.- func Function
Function called on the server each time a client subscribes. Inside the function,
this
is the publish handler object, described below. If the client passed arguments tosubscribe
, the function is called with the same arguments.
To publish records to clients, call Meteor.publish
on the server with
two parameters: the name of the record set, and a publish function
that Meteor will call each time a client subscribes to the name.
Publish functions can return a
Collection.Cursor
, in which case Meteor
will publish that cursor's documents. You can also return an array of
Collection.Cursor
s, in which case Meteor will publish all of the
cursors.
If you return multiple cursors in an array, they currently must all be from different collections. We hope to lift this restriction in a future release.
// server: publish the rooms collection, minus secret info.
Meteor.publish("rooms", function () {
return Rooms.find({}, {fields: {secretInfo: 0}});
});
// ... and publish secret info for rooms where the logged-in user
// is an admin. If the client subscribes to both streams, the records
// are merged together into the same documents in the Rooms collection.
Meteor.publish("adminSecretInfo", function () {
return Rooms.find({admin: this.userId}, {fields: {secretInfo: 1}});
});
// publish dependent documents and simulate joins
Meteor.publish("roomAndMessages", function (roomId) {
check(roomId, String);
return [
Rooms.find({_id: roomId}, {fields: {secretInfo: 0}}),
Messages.find({roomId: roomId})
];
});
Otherwise, the publish function should call the functions
added
(when a new document is added to the published record
set), changed
(when some fields on a document in the
record set are changed or cleared), and removed
(when
documents are removed from the published record set) to inform subscribers about
documents. These methods are provided by this
in your publish function.
Example:
// server: publish the current size of a collection
Meteor.publish("counts-by-room", function (roomId) {
var self = this;
check(roomId, String);
var count = 0;
var initializing = true;
var handle = Messages.find({roomId: roomId}).observeChanges({
added: function (id) {
count++;
if (!initializing)
self.changed("counts", roomId, {count: count});
},
removed: function (id) {
count--;
self.changed("counts", roomId, {count: count});
}
// don't care about moved or changed
});
// Observe only returns after the initial added callbacks have
// run. Now return an initial value and mark the subscription
// as ready.
initializing = false;
self.added("counts", roomId, {count: count});
self.ready();
// Stop observing the cursor when client unsubs.
// Stopping a subscription automatically takes
// care of sending the client any removed messages.
self.onStop(function () {
handle.stop();
});
});
// client: declare collection to hold count object
Counts = new Meteor.Collection("counts");
// client: subscribe to the count for the current room
Deps.autorun(function () {
Meteor.subscribe("counts-by-room", Session.get("roomId"));
});
// client: use the new collection
console.log("Current room has " +
Counts.findOne(Session.get("roomId")).count +
" messages.");
Meteor will emit a warning message if you call Meteor.publish
in a
project that includes the autopublish
package. Your publish function
will still work.
this.userId Server
Access inside the publish function. The id of the logged-in user, or null
if no user is logged in.
This is constant. However, if the logged-in user changes, the publish function is rerun with the new value.
this.added(collection, id, fields) Server
Call inside the publish function. Informs the subscriber that a document has been added to the record set.
Arguments
- collection String
The name of the collection that contains the new document.
- id String
The new document's ID.
- fields Object
The fields in the new document. If
_id
is present it is ignored.
this.changed(collection, id, fields) Server
Call inside the publish function. Informs the subscriber that a document in the record set has been modified.
Arguments
- collection String
The name of the collection that contains the changed document.
- id String
The changed document's ID.
- fields Object
The fields in the document that have changed, together with their new values. If a field is not present in
fields
it was left unchanged; if it is present infields
and has a value ofundefined
it was removed from the document. If_id
is present it is ignored.
this.removed(collection, id) Server
Call inside the publish function. Informs the subscriber that a document has been removed from the record set.
Arguments
- collection String
The name of the collection that the document has been removed from.
- id String
The ID of the document that has been removed.
this.ready() Server
Call inside the publish function. Informs the subscriber that an initial, complete snapshot of the record set has been sent. This will trigger a call on the client to the onReady
callback passed to Meteor.subscribe
, if any.
this.onStop(func) Server
Call inside the publish function. Registers a callback function to run when the subscription is stopped.
Arguments
- func Function
The callback function
If you call observe
or observeChanges
in your
publish handler, this is the place to stop the observes.
this.error(error) Server
Call inside the publish function. Stops this client's subscription, triggering a call on the client to the onError
callback passed to Meteor.subscribe
, if any. If error
is not a Meteor.Error
, it will be sanitized.
this.stop() Server
Call inside the publish function. Stops this client's subscription; the onError
callback is not invoked on the client.
Meteor.subscribe(name [, arg1, arg2, ... ] [, callbacks]) Client
Subscribe to a record set. Returns a handle that provides stop()
and ready()
methods.
Arguments
- name String
Name of the subscription. Matches name of server's publish() call.
- arg1, arg2, ... Any
Optional arguments passed to publisher function on server.
- callbacks Function or Object
Optional. May include
onError
andonReady
callbacks. If a function is passed instead of an object, it is interpreted as anonReady
callback.
When you subscribe to a record set, it tells the server to send records to the
client. The client stores these records in local Minimongo
collections, with the same name as the collection
argument used in the publish handler's added
, changed
, and removed
callbacks. Meteor will queue incoming attributes until you declare the
Meteor.Collection
on the client with the matching
collection name.
// okay to subscribe (and possibly receive data) before declaring
// the client collection that will hold it. assume "allplayers"
// publishes data from server's "players" collection.
Meteor.subscribe("allplayers");
...
// client queues incoming players records until ...
...
Players = new Meteor.Collection("players");
The client will see a document if the document is currently in the published record set of any of its subscriptions.
The onReady
callback is called with no arguments when the server
marks the subscription as ready. The onError
callback is
called with a Meteor.Error
if the subscription fails or is
terminated by the server.
Meteor.subscribe
returns a subscription handle, which is an object with the
following methods:
- stop()
Cancel the subscription. This will typically result in the server directing the client to remove the subscription's data from the client's cache.
- ready()
True if the server has marked the subscription as ready. A reactive data source.
If you call Meteor.subscribe
within a reactive computation,
for example using
Deps.autorun
, the subscription will automatically be
cancelled when the computation is invalidated or stopped; it's not necessary
to call stop
on
subscriptions made from inside autorun
. However, if the next iteration
of your run function subscribes to the same record set (same name and
parameters), Meteor is smart enough to skip a wasteful
unsubscribe/resubscribe. For example:
Deps.autorun(function () {
Meteor.subscribe("chat", {room: Session.get("current-room")});
Meteor.subscribe("privateMessages");
});
This subscribes you to the chat messages in the current room and to your private
messages. When you change rooms by calling Session.set("current-room",
"new-room")
, Meteor will subscribe to the new room's chat messages,
unsubscribe from the original room's chat messages, and continue to
stay subscribed to your private messages.
If more than one subscription sends conflicting values for a field (same collection name, document ID, and field name), then the value on the client will be one of the published values, chosen arbitrarily.
Methods
Methods are remote functions that Meteor clients can invoke.
Meteor.methods(methods) Anywhere
Defines functions that can be invoked over the network by clients.
Arguments
- methods Object
Dictionary whose keys are method names and values are functions.
Example:
Meteor.methods({
foo: function (arg1, arg2) {
check(arg1, String);
check(arg2, [Number]);
// .. do stuff ..
if (you want to throw an error)
throw new Meteor.Error(404, "Can't find my pants");
return "some return value";
},
bar: function () {
// .. do other stuff ..
return "baz";
}
});
Calling methods
on the server defines functions that can be called remotely by
clients. They should return an EJSON-able value or throw an
exception. Inside your method invocation, this
is bound to a method
invocation object, which provides the following:
isSimulation
: a boolean value, true if this invocation is a stub.unblock
: when called, allows the next method from this client to begin running.userId
: the id of the current user.setUserId
: a function that associates the current client with a user.
Calling methods
on the client defines stub functions associated with
server methods of the same name. You don't have to define a stub for
your method if you don't want to. In that case, method calls are just
like remote procedure calls in other systems, and you'll have to wait
for the results from the server.
If you do define a stub, when a client invokes a server method it will also run its stub in parallel. On the client, the return value of a stub is ignored. Stubs are run for their side-effects: they are intended to simulate the result of what the server's method will do, but without waiting for the round trip delay. If a stub throws an exception it will be logged to the console.
You use methods all the time, because the database mutators
(insert
, update
, remove
) are implemented
as methods. When you call any of these functions on the client, you're invoking
their stub version that update the local cache, and sending the same write
request to the server. When the server responds, the client updates the local
cache with the writes that actually occurred on the server.
this.userId Anywhere
The id of the user that made this method call, or null
if no user was logged in.
The user id is an arbitrary string — typically the id of the user record
in the database. You can set it with the setUserId
function. If you're using
the Meteor accounts system then this is handled for you.
this.setUserId(userId) Server
Set the logged in user.
Arguments
- userId String or null
The value that should be returned by
userId
on this connection.
Call this function to change the currently logged in user on the
connection that made this method call. This simply sets the value of
userId
for future method calls received on this connection. Pass
null
to log out the connection.
If you are using the built-in Meteor accounts system then this
should correspond to the _id
field of a document in the
Meteor.users
collection.
setUserId
is not retroactive. It affects the current method call and
any future method calls on the connection. Any previous method calls on
this connection will still see the value of userId
that was in effect
when they started.
this.isSimulation Anywhere
Access inside a method invocation. Boolean value, true if this invocation is a stub.
this.unblock() Server
Call inside a method invocation. Allow subsequent method from this client to begin running in a new fiber.
On the server, methods from a given client run one at a time. The N+1th
invocation from a client won't start until the Nth invocation
returns. However, you can change this by calling this.unblock
. This
will allow the N+1th invocation to start running in a new fiber.
new Meteor.Error(error, reason, details) Anywhere
This class represents a symbolic error thrown by a method.
Arguments
- error Number
A numeric error code, likely similar to an HTTP code (eg, 404, 500).
- reason String
Optional. A short human-readable summary of the error, like 'Not Found'.
- details String
Optional. Additional information about the error, like a textual stack trace.
If you want to return an error from a method, throw an exception. Methods can
throw any kind of exception. But Meteor.Error
is the only kind of error that
a server will send to the client. If a method function throws a different
exception, then it will be mapped to a sanitized version on the
wire. Specifically, if the sanitizedError
field on the thrown error is set to
a Meteor.Error
, then that error will be sent to the client. Otherwise, if no
sanitized version is available, the client gets
Meteor.Error(500, 'Internal server error')
.
Meteor.call(name, param1, param2, ... [, asyncCallback]) Anywhere
Invokes a method passing any number of arguments.
Arguments
- name String
Name of method to invoke
- param1, param2, ... EJSON
Optional method arguments
- asyncCallback Function
Optional callback, which is called asynchronously with the error or result after the method is complete. If not provided, the method runs synchronously if possible (see below).
This is how to invoke a method. It will run the method on the server. If a
stub is available, it will also run the stub on the client. (See also
Meteor.apply
, which is identical to Meteor.call
except that
you specify the parameters as an array instead of as separate arguments and you
can specify a few options controlling how the method is executed.)
If you include a callback function as the last argument (which can't be
an argument to the method, since functions aren't serializable), the
method will run asynchronously: it will return nothing in particular and
will not throw an exception. When the method is complete (which may or
may not happen before Meteor.call
returns), the callback will be
called with two arguments: error
and result
. If an error was thrown,
then error
will be the exception object. Otherwise, error
will be
undefined and the return value (possibly undefined) will be in result
.
// async call
Meteor.call('foo', 1, 2, function (error, result) { ... } );
If you do not pass a callback on the server, the method invocation will
block until the method is complete. It will eventually return the
return value of the method, or it will throw an exception if the method
threw an exception. (Possibly mapped to 500 Server Error if the
exception happened remotely and it was not a Meteor.Error
exception.)
// sync call
var result = Meteor.call('foo', 1, 2);
On the client, if you do not pass a callback and you are not inside a
stub, call
will return undefined
, and you will have no way to get
the return value of the method. That is because the client doesn't have
fibers, so there is not actually any way it can block on the remote
execution of a method.
Finally, if you are inside a stub on the client and call another
method, the other method is not executed (no RPC is generated, nothing
"real" happens). If that other method has a stub, that stub stands in
for the method and is executed. The method call's return value is the
return value of the stub function. The client has no problem executing
a stub synchronously, and that is why it's okay for the client to use
the synchronous Meteor.call
form from inside a method body, as
described earlier.
Meteor tracks the database writes performed by methods, both on the client and
the server, and does not invoke asyncCallback
until all of the server's writes
replace the stub's writes in the local cache. In some cases, there can be a lag
between the method's return value being available and the writes being visible:
for example, if another method still outstanding wrote to the same document, the
local cache may not be up to date until the other method finishes as well. If
you want to process the method's result as soon as it arrives from the server,
even if the method's writes are not available yet, you can specify an
onResultReceived
callback to Meteor.apply
.
Meteor.apply(name, params [, options] [, asyncCallback]) Anywhere
Invoke a method passing an array of arguments.
Arguments
- name String
Name of method to invoke
- params Array
Method arguments
- asyncCallback Function
Optional callback; same semantics as in
Meteor.call
.
Options
- wait Boolean
(Client only) If true, don't send this method until all previous method calls have completed, and don't send any subsequent method calls until this one is completed.
- onResultReceived Function
(Client only) This callback is invoked with the error or result of the method (just like
asyncCallback
) as soon as the error or result is available. The local cache may not yet reflect the writes performed by the method.
Meteor.apply
is just like Meteor.call
, except that the method arguments are
passed as an array rather than directly as arguments, and you can specify
options about how the client executes the method.
Server connections
These functions manage and inspect the network connection between the Meteor client and server.
Meteor.status() Client
Get the current connection status. A reactive data source.
This method returns the status of the connection between the client and the server. The return value is an object with the following fields:
- connected Boolean
True if currently connected to the server. If false, changes and method invocations will be queued up until the connection is reestablished.
- status String
Describes the current reconnection status. The possible values are
connected
(the connection is up and running),connecting
(disconnected and trying to open a new connection),failed
(permanently failed to connect; e.g., the client and server support different versions of DDP),waiting
(failed to connect and waiting to try to reconnect) andoffline
(user has disconnected the connection).- retryCount Number
The number of times the client has tried to reconnect since the connection was lost. 0 when connected.
- retryTime Number or undefined
The estimated time of the next reconnection attempt. To turn this into an interval until the next reconnection, use
retryTime - (new Date()).getTime()
. This key will be set only whenstatus
iswaiting
.- reason String or undefined
If
status
isfailed
, a description of why the connection failed.
Instead of using callbacks to notify you on changes, this is a reactive data source. You can use it in a template or computation to get realtime updates.
Meteor.reconnect() Client
Force an immediate reconnection attempt if the client is not connected to the server.
This method does nothing if the client is already connected.
Meteor.disconnect() Client
Disconnect the client from the server.
Call this method to disconnect from the server and stop all live data updates. While the client is disconnected it will not receive updates to collections, method calls will be queued until the connection is reestablished, and hot code push will be disabled.
Call Meteor.reconnect to reestablish the connection and resume data transfer.
This can be used to save battery on mobile devices when real time updates are not required.
DDP.connect(url) Anywhere
Connect to the server of a different Meteor application to subscribe to its document sets and invoke its remote methods.
Arguments
- url String
The URL of another Meteor application.
To call methods on another Meteor application or subscribe to its data
sets, call DDP.connect
with the URL of the application.
DDP.connect
returns an object which provides:
subscribe
- Subscribe to a record set. See Meteor.subscribe.call
- Invoke a method. See Meteor.call.apply
- Invoke a method with an argument array. See Meteor.apply.methods
- Define client-only stubs for methods defined on the remote server. See Meteor.methods.status
- Get the current connection status. See Meteor.status.reconnect
- See Meteor.reconnect.disconnect
- See Meteor.disconnect.onReconnect
- Set this to a function to be called as the first step of reconnecting. This function can call methods which will be executed before any other outstanding methods. For example, this can be used to re-establish the appropriate authentication context on the new connection.
By default, clients open a connection to the server from which they're loaded.
When you call Meteor.subscribe
, Meteor.status
, Meteor.call
, and
Meteor.apply
, you are using a connection back to that default
server.
Collections
Meteor stores data in collections. To get started, declare a
collection with new Meteor.Collection
.
new Meteor.Collection(name, [options]) Anywhere
Constructor for a Collection
Arguments
- name String
The name of the collection. If null, creates an unmanaged (unsynchronized) local collection.
Options
- connection Object
The Meteor connection that will manage this collection. Uses the default connection if not specified. Pass
null
to specify no connection. Unmanaged (name
is null) collections cannot specify a connection.- idGeneration String
The method of generating the
_id
fields of new documents in this collection. Possible values:'STRING'
: random strings'MONGO'
: randomMeteor.Collection.ObjectID
values
The default id generation technique is
'STRING'
.- transform Function
An optional transformation function. Documents will be passed through this function before being returned from
fetch
orfindOne
, and before being passed to callbacks ofobserve
,allow
, anddeny
.
Calling this function is analogous to declaring a model in a traditional ORM
(Object-Relation Mapper)-centric framework. It sets up a collection (a storage
space for records, or "documents") that can be used to store a particular type
of information, like users, posts, scores, todo items, or whatever matters to
your application. Each document is a EJSON object. It includes an _id
property whose value is unique in the collection, which Meteor will set when you
first create the document.
// common code on client and server declares livedata-managed mongo
// collection.
Chatrooms = new Meteor.Collection("chatrooms");
Messages = new Meteor.Collection("messages");
The function returns an object with methods to insert
documents in the collection, update
their properties, and
remove
them, and to find
the documents in the
collection that match arbitrary criteria. The way these methods work is
compatible with the popular Mongo database API. The same database API
works on both the client and the server (see below).
// return array of my messages
var myMessages = Messages.find({userId: Session.get('myUserId')}).fetch();
// create a new message
Messages.insert({text: "Hello, world!"});
// mark my first message as "important"
Messages.update(myMessages[0]._id, {$set: {important: true}});
If you pass a name
when you create the collection, then you are
declaring a persistent collection — one that is stored on the
server and seen by all users. Client code and server code can both
access the same collection using the same API.
Specifically, when you pass a name
, here's what happens:
On the server, a collection with that name is created on a backend Mongo server. When you call methods on that collection on the server, they translate directly into normal Mongo operations (after checking that they match your access control rules).
On the client, a Minimongo instance is created. Minimongo is essentially an in-memory, non-persistent implementation of Mongo in pure JavaScript. It serves as a local cache that stores just the subset of the database that this client is working with. Queries on the client (
find
) are served directly out of this cache, without talking to the server.When you write to the database on the client (
insert
,update
,remove
), the command is executed immediately on the client, and, simultaneously, it's shipped up to the server and executed there too. Thelivedata
package is responsible for this.
If you pass null
as the name
, then you're creating a local
collection. It's not synchronized anywhere; it's just a local scratchpad
that supports Mongo-style find
, insert
,
update
, and remove
operations. (On both the
client and the server, this scratchpad is implemented using Minimongo.)
By default, Meteor automatically publishes every document in your
collection to each connected client. To turn this behavior off, remove
the autopublish
package:
$ meteor remove autopublish
and instead call Meteor.publish
to specify which parts of
your collection should be published to which users.
// Create a collection called Posts and put a document in it. The
// document will be immediately visible in the local copy of the
// collection. It will be written to the server-side database
// a fraction of a second later, and a fraction of a second
// after that, it will be synchronized down to any other clients
// that are subscribed to a query that includes it (see
// Meteor.subscribe and autopublish)
Posts = new Meteor.Collection("posts");
Posts.insert({title: "Hello world", body: "First post"});
// Changes are visible immediately -- no waiting for a round trip to
// the server.
assert(Posts.find().count() === 1);
// Create a temporary, local collection. It works just like any other
// collection, but it doesn't send changes to the server, and it
// can't receive any data from subscriptions.
Scratchpad = new Meteor.Collection;
for (var i = 0; i < 10; i++)
Scratchpad.insert({number: i * 2});
assert(Scratchpad.find({number: {$lt: 9}}).count() === 5);
If you specify a transform
option to the Collection
or any of its retrieval
methods, documents are passed through the transform
function before being
returned or passed to callbacks. This allows you to add methods or otherwise
modify the contents of your collection from their database representation. You
can also specify transform
on a particular find
, findOne
, allow
, or
deny
call.
// An Animal class that takes a document in its constructor
Animal = function (doc) {
_.extend(this, doc);
};
_.extend(Animal.prototype, {
makeNoise: function () {
console.log(this.sound);
}
});
// Define a Collection that uses Animal as its document
Animals = new Meteor.Collection("Animals", {
transform: function (doc) { return new Animal(doc); }
});
// Create an Animal and call its makeNoise method
Animals.insert({name: "raptor", sound: "roar"});
Animals.findOne({name: "raptor"}).makeNoise(); // prints "roar"
transform
functions are not called reactively. If you want to add a
dynamically changing attribute to an object, do it with a function that computes
the value at the time it's called, not by computing the attribute at transform
time.
In this release, Minimongo has some limitations:
$pull
in modifiers can only accept certain kinds of selectors.$
to denote the matched array position is not supported in modifier.findAndModify
, upsert, aggregate functions, and map/reduce aren't supported.
All of these will be addressed in a future release. For full Minimongo release notes, see packages/minimongo/NOTES in the repository.
Minimongo doesn't currently have indexes. It's rare for this to be an issue, since it's unusual for a client to have enough data that an index is worthwhile.
collection.find(selector, [options]) Anywhere
Find the documents in a collection that match the selector.
Arguments
- selector Mongo selector, or String
The query
Options
- sort Sort specifier
Sort order (default: natural order)
- skip Number
Number of results to skip at the beginning
- limit Number
Maximum number of results to return
- fields Field specifier
(Server only) Dictionary of fields to return or exclude.
- reactive Boolean
(Client only) Default
true
; passfalse
to disable reactivity- transform Function
Overrides
transform
on theCollection
for this cursor. Passnull
to disable transformation.
find
returns a cursor. It does not immediately access the database or return
documents. Cursors provide fetch
to return all matching documents, map
and
forEach
to iterate over all matching documents, and observe
and
observeChanges
to register callbacks when the set of matching documents
changes.
Collection cursors are not query snapshots. If the database changes
between calling Collection.find
and fetching the
results of the cursor, or while fetching results from the cursor,
those changes may or may not appear in the result set.
Cursors are a reactive data source. The first time you retrieve a
cursor's documents with fetch
, map
, or forEach
inside a
reactive computation (eg, a template or
autorun
), Meteor will register a
dependency on the underlying data. Any change to the collection that
changes the documents in a cursor will trigger a recomputation. To
disable this behavior, pass {reactive: false}
as an option to
find
.
collection.findOne(selector, [options]) Anywhere
Finds the first document that matches the selector, as ordered by sort and skip options.
Arguments
- selector Mongo selector, or String
The query
Options
- sort Sort specifier
Sort order (default: natural order)
- skip Number
Number of results to skip at the beginning
- fields Field specifier
(Server only) Dictionary of fields to return or exclude.
- reactive Boolean
(Client only) Default true; pass false to disable reactivity
- transform Function
Overrides
transform
on theCollection
for this cursor. Passnull
to disable transformation.
Equivalent to find(selector, options).fetch()[0]
with
options.limit = 1
.
collection.insert(doc, [callback]) Anywhere
Insert a document in the collection. Returns its unique _id.
Arguments
- doc Object
The document to insert. May not yet have an _id attribute, in which case Meteor will generate one for you.
- callback Function
Optional. If present, called with an error object as the first argument and, if no error, the _id as the second.
Add a document to the collection. A document is just an object, and
its fields can contain any combination of EJSON-compatible datatypes
(arrays, objects, numbers, strings, null
, true, and false).
insert
will generate a unique ID for the object you pass, insert it
in the database, and return the ID. When insert
is called from
untrusted client code, it will be allowed only if passes any
applicable allow
and deny
rules.
On the server, if you don't provide a callback, then insert
blocks
until the database acknowledges the write, or throws an exception if
something went wrong. If you do provide a callback, insert
still
returns the ID immediately. Once the insert completes (or fails), the
callback is called with error and result arguments. In an error case,
result
is undefined. If the insert is successful, error
is
undefined and result
is the new document ID.
On the client, insert
never blocks. If you do not provide a callback
and the insert fails on the server, then Meteor will log a warning to
the console. If you provide a callback, Meteor will call that function
with error
and result
arguments. In an error case, result
is
undefined. If the insert is successful, error
is undefined and
result
is the new document ID.
Example:
var groceriesId = Lists.insert({name: "Groceries"});
Items.insert({list: groceriesId, name: "Watercress"});
Items.insert({list: groceriesId, name: "Persimmons"});
collection.update(selector, modifier, [options], [callback]) Anywhere
Modify one or more documents in the collection
Arguments
- selector Mongo selector, or object id
Specifies which documents to modify
- modifier Mongo modifier
Specifies how to modify the documents
- callback Function
Optional. If present, called with an error object as its argument.
Options
- multi Boolean
True to modify all matching documents; false to only modify one of the matching documents (the default).
Modify documents that match selector
according to modifier
(see
modifier documentation).
The behavior of update
differs depending on whether it is called by
trusted or untrusted code. Trusted code includes server code and
method code. Untrusted code includes client-side code such as event
handlers and a browser's JavaScript console.
Trusted code can modify multiple documents at once by setting
multi
to true, and can use an arbitrary Mongo selector to find the documents to modify. It bypasses any access control rules set up byallow
anddeny
.Untrusted code can only modify a single document at once, specified by its
_id
. The modification is allowed only after checking any applicableallow
anddeny
rules.
On the server, if you don't provide a callback, then update
blocks
until the database acknowledges the write, or throws an exception if
something went wrong. If you do provide a callback, update
returns
immediately. Once the update completes, the callback is called with a
single error argument in the case of failure, or no arguments if the
update was successful.
On the client, update
never blocks. If you do not provide a callback
and the update fails on the server, then Meteor will log a warning to
the console. If you provide a callback, Meteor will call that function
with an error argument if there was an error, or no arguments if the
update was successful.
Client example:
// When the givePoints button in the admin dashboard is pressed,
// give 5 points to the current player. The new score will be
// immediately visible on everyone's screens.
Template.adminDashboard.events({
'click .givePoints': function () {
Players.update(Session.get("currentPlayer"), {$inc: {score: 5}});
}
});
Server example:
// Give the "Winner" badge to each user with a score greater than
// 10. If they are logged in and their badge list is visible on the
// screen, it will update automatically as they watch.
Meteor.methods({
declareWinners: function () {
Players.update({score: {$gt: 10}},
{$addToSet: {badges: "Winner"}},
{multi: true});
}
});
The Mongo upsert
feature is not implemented.
collection.remove(selector, [callback]) Anywhere
Remove documents from the collection
Arguments
- selector Mongo selector, or object id
Specifies which documents to remove
- callback Function
Optional. If present, called with an error object as its argument.
Find all of the documents that match selector
and delete them from
the collection.
The behavior of remove
differs depending on whether it is called by
trusted or untrusted code. Trusted code includes server code and
method code. Untrusted code includes client-side code such as event
handlers and a browser's JavaScript console.
Trusted code can use an arbitrary Mongo selector to find the documents to remove, and can remove more than one document at once by passing a selector that matches multiple documents. It bypasses any access control rules set up by
allow
anddeny
.As a safety measure, if
selector
is omitted (or isundefined
), no documents will be removed. Setselector
to{}
if you really want to remove all documents from your collection.Untrusted code can only remove a single document at a time, specified by its
_id
. The document is removed only after checking any applicableallow
anddeny
rules.
On the server, if you don't provide a callback, then remove
blocks
until the database acknowledges the write, or throws an exception if
something went wrong. If you do provide a callback, remove
returns
immediately. Once the remove completes, the callback is called with a
single error argument in the case of failure, or no arguments if the
remove was successful.
On the client, remove
never blocks. If you do not provide a callback
and the remove fails on the server, then Meteor will log a warning to
the console. If you provide a callback, Meteor will call that function
with an error argument if there was an error, or no arguments if the
remove was successful.
Client example:
// When the remove button is clicked on a chat message, delete
// that message.
Template.chat.events({
'click .remove': function () {
Messages.remove(this._id);
}
});
Server example:
// When the server starts, clear the log, and delete all players
// with a karma of less than -2.
Meteor.startup(function () {
if (Meteor.isServer) {
Logs.remove({});
Players.remove({karma: {$lt: -2}});
}
});
collection.allow(options) Server
Allow users to write directly to this collection from client code, subject to limitations you define.
Options
- insert, update, remove Function
Functions that look at a proposed modification to the database and return true if it should be allowed.
- fetch Array of String
Optional performance enhancement. Limits the fields that will be fetched from the database for inspection by your
update
andremove
functions.- transform Function
Overrides
transform
on theCollection
. Passnull
to disable transformation.
When a client calls insert
, update
, or remove
on a collection, the
collection's allow
and deny
callbacks are called
on the server to determine if the write should be allowed. If at least
one allow
callback allows the write, and no deny
callbacks deny the
write, then the write is allowed to proceed.
These checks are run only when a client tries to write to the database
directly, for example by calling update
from inside an event
handler. Server code is trusted and isn't subject to allow
and deny
restrictions. That includes methods that are called with Meteor.call
— they are expected to do their own access checking rather than
relying on allow
and deny
.
You can call allow
as many times as you like, and each call can
include any combination of insert
, update
, and remove
functions. The functions should return true
if they think the
operation should be allowed. Otherwise they should return false
, or
nothing at all (undefined
). In that case Meteor will continue
searching through any other allow
rules on the collection.
The available callbacks are:
- insert(userId, doc)
The user
userId
wants to insert the documentdoc
into the collection. Returntrue
if this should be allowed.- update(userId, doc, fieldNames, modifier)
The user
userId
wants to update a documentdoc
. (doc
is the current version of the document from the database, without the proposed update.) Returntrue
to permit the change.fieldNames
is an array of the (top-level) fields indoc
that the client wants to modify, for example['name',
'score']
.modifier
is the raw Mongo modifier that the client wants to execute, for example{$set: {'name.first': "Alice"}, $inc: {score: 1}}
.Only Mongo modifiers are supported (operations like
$set
and$push
). If the user tries to replace the entire document rather than use $-modifiers, the request will be denied without checking theallow
functions.- remove(userId, doc)
The user
userId
wants to removedoc
from the database. Returntrue
to permit this.
When calling update
or remove
Meteor will by default fetch the
entire document doc
from the database. If you have large documents
you may wish to fetch only the fields that are actually used by your
functions. Accomplish this by setting fetch
to an array of field
names to retrieve.
Example:
// Create a collection where users can only modify documents that
// they own. Ownership is tracked by an 'owner' field on each
// document. All documents must be owned by the user that created
// them and ownership can't be changed. Only a document's owner
// is allowed to delete it, and the 'locked' attribute can be
// set on a document to prevent its accidental deletion.
Posts = new Meteor.Collection("posts");
Posts.allow({
insert: function (userId, doc) {
// the user must be logged in, and the document must be owned by the user
return (userId && doc.owner === userId);
},
update: function (userId, doc, fields, modifier) {
// can only change your own documents
return doc.owner === userId;
},
remove: function (userId, doc) {
// can only remove your own documents
return doc.owner === userId;
},
fetch: ['owner']
});
Posts.deny({
update: function (userId, docs, fields, modifier) {
// can't change owners
return _.contains(fields, 'owner');
},
remove: function (userId, doc) {
// can't remove locked documents
return doc.locked;
},
fetch: ['locked'] // no need to fetch 'owner'
});
If you never set up any allow
rules on a collection then all client
writes to the collection will be denied, and it will only be possible to
write to the collection from server-side code. In this case you will
have to create a method for each possible write that clients are allowed
to do. You'll then call these methods with Meteor.call
rather than
having the clients call insert
, update
, and remove
directly on the
collection.
Meteor also has a special "insecure mode" for quickly prototyping new
applications. In insecure mode, if you haven't set up any allow
or deny
rules on a collection, then all users have full write access to the
collection. This is the only effect of insecure mode. If you call allow
or
deny
at all on a collection, even Posts.allow({})
, then access is checked
just like normal on that collection. New Meteor projects start in insecure
mode by default. To turn it off just run $ meteor remove insecure
.
collection.deny(options) Server
Override allow
rules.
Options
- insert, update, remove Function
Functions that look at a proposed modification to the database and return true if it should be denied, even if an
allow
rule says otherwise.- fetch Array of Strings
Optional performance enhancement. Limits the fields that will be fetched from the database for inspection by your
update
andremove
functions.- transform Function
Overrides
transform
on theCollection
. Passnull
to disable transformation.
This works just like allow
, except it lets you
make sure that certain writes are definitely denied, even if there is an
allow
rule that says that they should be permitted.
When a client tries to write to a collection, the Meteor server first
checks the collection's deny
rules. If none of them return true then
it checks the collection's allow
rules. Meteor allows the write only
if no deny
rules return true
and at least one allow
rule returns
true
.
Cursors
To create a cursor, use find
. To access the documents in a
cursor, use forEach
, map
, or fetch
.
cursor.forEach(callback) Anywhere
Call callback
once for each matching document, sequentially and synchronously.
Arguments
- callback Function
Function to call.
When called from a reactive computation, forEach
registers dependencies on
the matching documents.
Examples:
// Print the titles of the five top-scoring posts
var topPosts = Posts.find({}, {sort: {score: -1}, limit: 5});
var count = 0;
topPosts.forEach(function (post) {
console.log("Title of post " + count + ": " + post.title);
count += 1;
});
cursor.map(callback) Anywhere
Map callback over all matching documents. Returns an Array.
Arguments
- callback Function
Function to call.
When called from a reactive computation, map
registers dependencies on
the matching documents.
On the server, if callback
yields, other calls to callback
may occur while
the first call is waiting. If strict sequential execution is necessary, use
forEach
instead.
cursor.fetch() Anywhere
Return all matching documents as an Array.
When called from a reactive computation, fetch
registers dependencies on
the matching documents.
cursor.count() Anywhere
Returns the number of documents that match a query.
// Display a count of posts matching certain criteria. Automatically
// keep it updated as the database changes.
var frag = Meteor.render(function () {
var highScoring = Posts.find({score: {$gt: 10}});
return "<p>There are " + highScoring.count() + " posts with " +
"scores greater than 10</p>";
});
document.body.appendChild(frag);
Unlike the other functions, count
registers a dependency only on the
number of matching documents. (Updates that just change or reorder the
documents in the result set will not trigger a recomputation.)
cursor.rewind() Anywhere
Resets the query cursor.
The forEach
, map
, or fetch
methods can only be called once on a
cursor. To access the data in a cursor more than once, use rewind
to
reset the cursor.
cursor.observe(callbacks) Anywhere
Watch a query. Receive callbacks as the result set changes.
Arguments
- callbacks Object
Functions to call to deliver the result set as it changes
Establishes a live query that invokes callbacks when the result of
the query changes. The callbacks receive the entire contents of the
document that was affected, as well as its old contents, if
applicable. If you only need to receive the fields that changed, see
observeChanges
.
callbacks
may have the following functions as properties:
- added(document) or
- addedAt(document, atIndex, before)
-
A new document
document
entered the result set. The new document appears at positionatIndex
. It is immediately before the document whose_id
isbefore
.before
will benull
if the new document is at the end of the results. - changed(newDocument, oldDocument) or
- changedAt(newDocument, oldDocument, atIndex)
-
The contents of a document were previously
oldDocument
and are nownewDocument
. The position of the changed document isatIndex
. - removed(oldDocument) or
- removedAt(oldDocument, atIndex)
-
The document
oldDocument
is no longer in the result set. It used to be at positionatIndex
. - movedTo(document, fromIndex, toIndex, before)
A document changed its position in the result set, from
fromIndex
totoIndex
(which is before the document with idbefore
). Its current contents isdocument
.
Use added
, changed
, and removed
when you don't care about the
order of the documents in the result set. They are more efficient than
addedAt
, changedAt
, and removedAt
.
Before observe
returns, added
(or addedAt
) will be called zero
or more times to deliver the initial results of the query.
observe
returns a live query handle, which is an object with a stop
method.
Call stop
with no arguments to stop calling the callback functions and tear
down the query. The query will run forever until you call this. If
observe
is called from a Deps.autorun
computation, it is automatically
stopped when the computation is rerun or stopped.
(If the cursor was created with the option reactive
set to false, it will
only deliver the initial results and will not call any further callbacks;
it is not necessary to call stop
on the handle.)
cursor.observeChanges(callbacks) Anywhere
Watch a query. Receive callbacks as the result set changes. Only the differences between the old and new documents are passed to the callbacks.
Arguments
- callbacks Object
Functions to call to deliver the result set as it changes
Establishes a live query that invokes callbacks when the result of
the query changes. In contrast to observe
,
observeChanges
provides only the difference between the old and new
result set, not the entire contents of the document that changed.
callbacks
may have the following functions as properties:
- added(id, fields) or
- addedBefore(id, fields, before)
-
A new document entered the result set. It has the
id
andfields
specified.fields
contains all fields of the document excluding the_id
field. The new document is before the document identified bybefore
, or at the end ifbefore
isnull
. - changed(id, fields)
The document identified by
id
has changed.fields
contains the changed fields with their new values. If a field was removed from the document then it will be present infields
with a value ofundefined
.- movedBefore(id, before)
The document identified by
id
changed its position in the ordered result set, and now appears before the document identified bybefore
.- removed(id)
The document identified by
id
was removed from the result set.
observeChanges
is significantly more efficient if you do not use
addedBefore
or movedBefore
.
Before observeChanges
returns, added
(or addedBefore
) will be called
zero or more times to deliver the initial results of the query.
observeChanges
returns a live query handle, which is an object with a stop
method. Call stop
with no arguments to stop calling the callback functions
and tear down the query. The query will run forever until you call this.
If
observeChanges
is called from a Deps.autorun
computation, it is automatically
stopped when the computation is rerun or stopped.
(If the cursor was created with the option reactive
set to false, it will
only deliver the initial results and will not call any further callbacks;
it is not necessary to call stop
on the handle.)
Unlike observe
, observeChanges
does not provide absolute position
information (that is, atIndex
positions rather than before
positions.) This is for efficiency.
Example:
// Keep track of how many administrators are online.
var count = 0;
var query = Users.find({admin: true, onlineNow: true});
var handle = query.observeChanges({
added: function (id, user) {
count++;
console.log(user.name + " brings the total to " + count + " admins.");
},
removed: function () {
count--;
console.log("Lost one. We're now down to " + count + " admins.");
}
});
// After five seconds, stop keeping the count.
setTimeout(function () {handle.stop();}, 5000);
new Meteor.Collection.ObjectID(hexString) Anywhere
Create a Mongo-style ObjectID
. If you don't specify a hexString
, the ObjectID
will generated randomly (not using MongoDB's ID construction rules).
Arguments
- hexString String
Optional. The 24-character hexadecimal contents of the ObjectID to create
Meteor.Collection.ObjectID
follows the same API as the Node MongoDB driver
ObjectID
class. Note that you must use the equals
method (or EJSON.equals
) to
compare them; the ===
operator will not work. If you are writing generic code
that needs to deal with _id
fields that may be either strings or ObjectID
s, use
EJSON.equals
instead of ===
to compare them.
ObjectID
values created by Meteor will not have meaningful answers to their getTimestamp
method, since Meteor currently constructs them fully randomly.
Session
Session
provides a global object on the client that you can use to
store an arbitrary set of key-value pairs. Use it to store things like
the currently selected item in a list.
What's special about Session
is that it's reactive. If
you call Session.get
("currentList")
from inside a template, the template will automatically be rerendered
whenever Session.set
("currentList", x)
is called.
Session.set(key, value) Client
Set a variable in the session. Notify any listeners that the value has changed (eg: redraw templates, and rerun any Deps.autorun
computations, that called Session.get
on this key
.)
Arguments
- key String
The key to set, eg,
selectedItem
- value EJSON-able object or undefined
The new value for
key
Example:
Deps.autorun(function () {
Meteor.subscribe("chat-history", {room: Session.get("currentRoomId")});
});
// Causes the function passed to Deps.autorun to be re-run, so
// that the chat-history subscription is moved to the room "home".
Session.set("currentRoomId", "home");
Session.setDefault(key, value) Client
Set a variable in the session if it is undefined. Otherwise works exactly the same as Session.set
.
Arguments
- key String
The key to set, eg,
selectedItem
- value EJSON-able object or undefined
The new value for
key
This is useful in initialization code, to avoid re-initializing a session variable every time a new version of your app is loaded.
Session.get(key) Client
Get the value of a session variable. If inside a reactive computation, invalidate the computation the next time the value of the variable is changed by Session.set
. This returns a clone of the session value, so if it's an object or an array, mutating the returned value has no effect on the value stored in the session.
Arguments
- key String
The name of the session variable to return
Example:
Session.set("enemy", "Eastasia");
var frag = Meteor.render(function () {
return "<p>We've always been at war with " +
Session.get("enemy") + "</p>";
});
// Page will say "We've always been at war with Eastasia"
document.body.append(frag);
// Page will change to say "We've always been at war with Eurasia"
Session.set("enemy", "Eurasia");
Session.equals(key, value) Client
Test if a session variable is equal to a value. If inside a reactive computation, invalidate the computation the next time the variable changes to or from the value.
Arguments
- key String
The name of the session variable to test
- value String, Number, Boolean, null, or undefined
The value to test against
If value is a scalar, then these two expressions do the same thing:
(1) Session.get("key") === value
(2) Session.equals("key", value)
... but the second one is always better. It triggers fewer invalidations (template redraws), making your program more efficient.
Example:
<template name="postsView">
{{! Show a dynamically updating list of items. Let the user click on an
item to select it. The selected item is given a CSS class so it
can be rendered differently. }}
{{#each posts}}
{{> postItem }}
{{/each}}
</template>
<template name="postItem">
<div class="{{postClass}}">{{title}}</div>
</template>
///// in JS file
Template.postsView.posts = function() {
return Posts.find();
};
Template.postItem.postClass = function() {
return Session.equals("selectedPost", this._id) ?
"selected" : "";
};
Template.postItem.events({
'click': function() {
Session.set("selectedPost", this._id);
}
});
// Using Session.equals here means that when the user clicks
// on an item and changes the selection, only the newly selected
// and the newly unselected items are re-rendered.
//
// If Session.get had been used instead of Session.equals, then
// when the selection changed, all the items would be re-rendered.
For object and array session values, you cannot use Session.equals
; instead,
you need to use the underscore
package and write
_.isEqual(Session.get(key), value)
.
Accounts
The Meteor Accounts system builds on top of the userId
support in
publish
and methods
. The core
packages add the concept of user documents stored in the database, and
additional packages add secure password
authentication, integration with third party
login services, and a pre-built user
interface.
The basic Accounts system is in the accounts-base
package, but
applications typically include this automatically by adding one of the
login provider packages: accounts-password
, accounts-facebook
,
accounts-github
, accounts-google
, accounts-meetup
,
accounts-twitter
, or accounts-weibo
.
Meteor.user() Anywhere but publish functions
Get the current user record, or null
if no user is logged in. A reactive data source.
Retrieves the user record for the current user from
the Meteor.users
collection.
On the client, this will be the subset of the fields in the document that
are published from the server (other fields won't be available on the
client). By default the server publishes username
, emails
, and
profile
. See Meteor.users
for more on
the fields used in user documents.
Meteor.userId() Anywhere but publish functions
Get the current user id, or null
if no user is logged in. A reactive data source.
Meteor.users Anywhere
A Meteor.Collection containing user documents.
This collection contains one document per registered user. Here's an example user document:
{
_id: "bbca5d6a-2156-41c4-89da-0329e8c99a4f", // Meteor.userId()
username: "cool_kid_13", // unique name
emails: [
// each email address can only belong to one user.
{ address<EMAIL_ADDRESS>verified: true },
{ address<EMAIL_ADDRESS>verified: false }
],
createdAt:<PHONE_NUMBER>042,
profile: {
// The profile is writable by the user by default.
name: "Joe Schmoe"
},
services: {
facebook: {
id: "709050", // facebook id
accessToken: "AAACCgdX7G2...AbV9AZDZD"
},
resume: {
loginTokens: [
{ token: "97e8c205-c7e4-47c9-9bea-8e2ccc0694cd",
when:<PHONE_NUMBER>048 }
]
}
}
}
A user document can contain any data you want to store about a user. Meteor treats the following fields specially:
username
: a unique String identifying the user.emails
: an Array of Objects with keysaddress
andverified
; an email address may belong to at most one user.verified
is a Boolean which is true if the user has verified the address with a token sent over email.createdAt
: a numeric timestamp (milliseconds since January 1 1970) of the time the user document was created.profile
: an Object which (by default) the user can create and update with any data.services
: an Object containing data used by particular login services. For example, itsreset
field contains tokens used by forgot password links, and itsresume
field contains tokens used to keep you logged in between sessions.
Like all Meteor.Collections, you can access all documents on the server, but only those specifically published by the server are available on the client.
By default, the current user's username
, emails
and profile
are
published to the client. You can publish additional fields for the
current user with:
Meteor.publish("userData", function () {
return Meteor.users.find({_id: this.userId},
{fields: {'other': 1, 'things': 1}});
});
If the autopublish package is installed, information about all users
on the system is published to all clients. This includes username
,
profile
, and any fields in services
that are meant to be public
(eg services.facebook.id
,
services.twitter.screenName
). Additionally, when using autopublish
more information is published for the currently logged in user,
including access tokens. This allows making API calls directly from
the client for services that allow this.
Users are by default allowed to specify their own profile
field with
Accounts.createUser
and modify it with
Meteor.users.update
. To allow users to edit additional fields, use
Meteor.users.allow
. To forbid users from making any modifications to
their user document:
Meteor.users.deny({update: function () { return true; }});
Meteor.loggingIn() Client
True if a login method (such as Meteor.loginWithPassword
, Meteor.loginWithFacebook
, or Accounts.createUser
) is currently in progress. A reactive data source.
For example, the accounts-ui
package uses this to display an
animation while the login request is being processed.
Meteor.logout([callback]) Client
Log the user out.
Arguments
- callback Function
Optional callback. Called with no arguments on success, or with a single
Error
argument on failure.
Meteor.loginWithPassword(user, password, [callback]) Client
Log the user in with a password.
Arguments
- user Object or String
Either a string interpreted as a username or an email; or an object with a single key:
email
,username
orid
.- password String
The user's password. This is not sent in plain text over the wire — it is secured with SRP.
- callback Function
Optional callback. Called with no arguments on success, or with a single
Error
argument on failure.
This function is provided by the accounts-password
package. See the
Passwords section below.
Meteor.loginWithExternalService([options], [callback]) Client
Log the user in using an external service.
Arguments
- callback Function
Optional callback. Called with no arguments on success, or with a single
Error
argument on failure.
Options
- requestPermissions Array of Strings
A list of permissions to request from the user.
- requestOfflineToken Boolean
If true, asks the user for permission to act on their behalf when offline. This stores an additional offline token in the
services
field of the user document. Currently only supported with Google.- forceApprovalPrompt Boolean
If true, forces the user to approve the app's permissions, even if previously approved. Currently only supported with Google.
These functions initiate the login process with an external service (eg: Facebook, Google, etc), using OAuth. When called they open a new pop-up window that loads the provider's login page. Once the user has logged in with the provider, the pop-up window is closed and the Meteor client logs in to the Meteor server with the information provided by the external service.
In addition to identifying the user to your application, some services
have APIs that allow you to take action on behalf of the user. To
request specific permissions from the user, pass the
requestPermissions
option the login function. This will cause the user
to be presented with an additional page in the pop-up dialog to permit
access to their data. The user's accessToken
— with permissions
to access the service's API — is stored in the services
field of
the user document. The supported values for requestPermissions
differ
for each login service and are documented on their respective developer
sites:
- Facebook: http://developers.facebook.com/docs/authentication/permissions/
- GitHub: http://developer.github.com/v3/oauth/#scopes
- Google: https://developers.google.com/accounts/docs/OAuth2Login#scopeparameter
- Meetup: http://www.meetup.com/meetup_api/auth/#oauth2-scopes
- Twitter, Weibo:
requestPermissions
currently not supported
External login services typically require registering and configuring
your application before use. The easiest way to do this is with the
accounts-ui
package which presents a step-by-step guide
to configuring each service. However, the data can be also be entered
manually in the Accounts.loginServiceConfiguration
collection. For
example:
// first, remove configuration entry in case service is already configured
Accounts.loginServiceConfiguration.remove({
service: "weibo"
});
Accounts.loginServiceConfiguration.insert({
service: "weibo",
clientId: "1292962797",
secret: "75a730b58f5691de5522789070c319bc"
});
Each external service has its own login provider package and login function. For
example, to support GitHub login, run $ meteor add accounts-github
and use the
Meteor.loginWithGithub
function:
Meteor.loginWithGithub({
requestPermissions: ['user', 'public_repo']
}, function (err) {
if (err)
Session.set('errorMessage', err.reason || 'Unknown error');
});
{{currentUser}} Handlebars templates
Calls Meteor.user(). Use {{#if currentUser}}
to check whether the user is logged in.
{{loggingIn}} Handlebars templates
Calls Meteor.loggingIn().
Accounts.config(options) Anywhere
Set global accounts options.
Options
- sendVerificationEmail Boolean
New users with an email address will receive an address verification email.
- forbidClientAccountCreation Boolean
Calls to
createUser
from the client will be rejected. In addition, if you are using accounts-ui, the "Create account" link will not be available.
Accounts.ui.config(options) Client
Configure the behavior of {{loginButtons}}
.
Options
- requestPermissions Object
Which permissions to request from the user for each external service.
- requestOfflineToken Object
To ask the user for permission to act on their behalf when offline, map the relevant external service to
true
. Currently only supported with Google. See Meteor.loginWithExternalService for more details.- passwordSignupFields String
Which fields to display in the user creation form. One of '
USERNAME_AND_EMAIL
', 'USERNAME_AND_OPTIONAL_EMAIL
', 'USERNAME_ONLY
', or 'EMAIL_ONLY
' (default).
Example:
Accounts.ui.config({
requestPermissions: {
facebook: ['user_likes'],
github: ['user', 'repo']
},
requestOfflineToken: {
google: true
},
passwordSignupFields: 'USERNAME_AND_OPTIONAL_EMAIL'
});
Accounts.validateNewUser(func) Server
Set restrictions on new user creation.
Arguments
- func Function
Called whenever a new user is created. Takes the new user object, and returns true to allow the creation or false to abort.
This can be called multiple times. If any of the functions return false
or
throw an error, the new user creation is aborted. To set a specific error
message (which will be displayed by accounts-ui
), throw a new
Meteor.Error
.
Example:
// Validate username, sending a specific error message on failure.
Accounts.validateNewUser(function (user) {
if (user.username && user.username.length >= 3)
return true;
throw new Meteor.Error(403, "Username must have at least 3 characters");
});
// Validate username, without a specific error message.
Accounts.validateNewUser(function (user) {
return user.username !== "root";
});
Accounts.onCreateUser(func) Server
Customize new user creation.
Arguments
- func Function
Called whenever a new user is created. Return the new user object, or throw an
Error
to abort the creation.
Use this when you need to do more than simply accept or reject new user creation. With this function you can programatically control the contents of new user documents.
The function you pass will be called with two arguments: options
and
user
. The options
argument comes
from Accounts.createUser
for
password-based users or from an external service login flow. options
may come
from an untrusted client so make sure to validate any values you read from
it. The user
argument is created on the server and contains a
proposed user object with all the automatically generated fields
required for the user to log in.
The function should return the user document (either the one passed in or a
newly-created object) with whatever modifications are desired. The returned
document is inserted directly into the Meteor.users
collection.
The default create user function simply copies options.profile
into
the new user document. Calling onCreateUser
overrides the default
hook. This can only be called once.
Example:
// Support for playing D&D: Roll 3d6 for dexterity
Accounts.onCreateUser(function(options, user) {
var d6 = function () { return Math.floor(Random.fraction() * 6) + 1; };
user.dexterity = d6() + d6() + d6();
// We still want the default hook's 'profile' behavior.
if (options.profile)
user.profile = options.profile;
return user;
});
Passwords
The accounts-password
package contains a full system for password-based
authentication. In addition to the basic username and password-based
sign-in process, it also supports email-based sign-in including
address verification and password recovery emails.
Unlike most web applications, the Meteor client does not send the user's password directly to the server. It uses the Secure Remote Password protocol to ensure the server never sees the user's plain-text password. This helps protect against embarrassing password leaks if the server's database is compromised.
To add password support to your application, run $ meteor add
accounts-password
. You can construct your own user interface using the
functions below, or use the accounts-ui
package to
include a turn-key user interface for password-based sign-in.
Accounts.createUser(options, [callback]) Anywhere
Create a new user.
Arguments
- callback Function
Client only, optional callback. Called with no arguments on success, or with a single
Error
argument on failure.
Options
- username String
A unique name for this user.
- email String
The user's email address.
- password String
The user's password. This is not sent in plain text over the wire.
- profile Object
The user's profile, typically including the
name
field.
On the client, this function logs in as the newly created user on successful completion. On the server, it returns the newly created user id.
On the client, you must pass password
and one of username
or email
— enough information for the user to be able to log in again
later. On the server, you can pass any subset of these options, but the
user will not be able to log in until it has an identifier and a
password.
To create an account without a password on the server and still let the
user pick their own password, call createUser
with the email
option
and then
call Accounts.sendEnrollmentEmail
. This
will send the user an email with a link to set their initial password.
By default the profile
option is added directly to the new user document. To
override this behavior, use Accounts.onCreateUser
.
This function is only used for creating users with passwords. The external service login flows do not use this function.
Accounts.changePassword(oldPassword, newPassword, [callback]) Client
Change the current user's password. Must be logged in.
Arguments
- oldPassword String
The user's current password. This is not sent in plain text over the wire.
- newPassword String
A new password for the user. This is not sent in plain text over the wire.
- callback Function
Optional callback. Called with no arguments on success, or with a single
Error
argument on failure.
Accounts.forgotPassword(options, [callback]) Client
Request a forgot password email.
Arguments
- callback Function
Optional callback. Called with no arguments on success, or with a single
Error
argument on failure.
Options
- email String
The email address to send a password reset link.
This triggers a call
to Accounts.sendResetPasswordEmail
on the server. Pass the token the user receives in this email
to Accounts.resetPassword
to
complete the password reset process.
If you are using the accounts-ui
package, this is handled
automatically. Otherwise, it is your responsiblity to prompt the user for the
new password and call resetPassword
.
Accounts.resetPassword(token, newPassword, [callback]) Client
Reset the password for a user using a token received in email. Logs the user in afterwards.
Arguments
- token String
The token retrieved from the reset password URL.
- newPassword String
A new password for the user. This is not sent in plain text over the wire.
- callback Function
Optional callback. Called with no arguments on success, or with a single
Error
argument on failure.
This function accepts tokens generated
by Accounts.sendResetPasswordEmail
and
Accounts.sendEnrollmentEmail
.
Accounts.setPassword(userId, newPassword) Server
Forcibly change the password for a user.
Arguments
- userId String
The id of the user to update.
- newPassword String
A new password for the user.
Accounts.verifyEmail(token, [callback]) Client
Marks the user's email address as verified. Logs the user in afterwards.
Arguments
- token String
The token retrieved from the verification URL.
- callback Function
Optional callback. Called with no arguments on success, or with a single
Error
argument on failure.
This function accepts tokens generated
by Accounts.sendVerificationEmail
. It
sets the emails.verified
field in the user record.
Accounts.sendResetPasswordEmail(userId, [email]) Server
Send an email with a link the user can use to reset their password.
Arguments
- userId String
The id of the user to send email to.
- email String
Optional. Which address of the user's to send the email to. This address must be in the user's
emails
list. Defaults to the first email in the list.
The token in this email should be passed
to Accounts.resetPassword
.
To customize the contents of the email, see
Accounts.emailTemplates
.
Accounts.sendEnrollmentEmail(userId, [email]) Server
Send an email with a link the user can use to set their initial password.
Arguments
- userId String
The id of the user to send email to.
- email String
Optional. Which address of the user's to send the email to. This address must be in the user's
emails
list. Defaults to the first email in the list.
The token in this email should be passed
to Accounts.resetPassword
.
To customize the contents of the email, see
Accounts.emailTemplates
.
Accounts.sendVerificationEmail(userId, [email]) Server
Send an email with a link the user can use verify their email address.
Arguments
- userId String
The id of the user to send email to.
- email String
Optional. Which address of the user's to send the email to. This address must be in the user's
emails
list. Defaults to the first unverified email in the list.
The token in this email should be passed
to Accounts.verifyEmail
.
To customize the contents of the email, see
Accounts.emailTemplates
.
Accounts.emailTemplates Anywhere
Options to customize emails sent from the Accounts system.
This is an Object
with several fields that are used to generate text
for the emails sent by sendResetPasswordEmail
, sendEnrollmentEmail
,
and sendVerificationEmail
.
Override fields of the object by assigning to them:
from
: AString
with an RFC5322 From address. By default, the email is sent<EMAIL_ADDRESS>. If you wish to receive email from users asking for help with their account, be sure to set this to an email address that you can receive email at.siteName
: The public name of your application. Defaults to the DNS name of the application (eg:awesome.meteor.com
).resetPassword
: AnObject
with two fields:resetPassword.subject
: AFunction
that takes a user object and returns aString
for the subject line of a reset password email.resetPassword.text
: AFunction
that takes a user object and a url, and returns the body text for a reset password email.
enrollAccount
: Same asresetPassword
, but for initial password setup for new accounts.verifyEmail
: Same asresetPassword
, but for verifying the users email address.
Example:
Accounts.emailTemplates.siteName = "AwesomeSite";
Accounts.emailTemplates.from = "AwesomeSite Admin<EMAIL_ADDRESS>Accounts.emailTemplates.enrollAccount.subject = function (user) {
return "Welcome to Awesome Town, " + user.profile.name;
};
Accounts.emailTemplates.enrollAccount.text = function (user, url) {
return "You have been selected to participate in building a better future!"
+ " To activate your account, simply click the link below:\n\n"
+ url;
};
Templates
A template that you declare as <template name="foo"> ... </template>
can be accessed as the function Template.foo
, which
returns a string of HTML when called.
The same template may occur many times on the page, and these occurrences are called template instances. Template instances have a life cycle of being created, put into the document, and later taken out of the document and destroyed. Meteor manages these stages for you, including determining when a template instance has been removed or replaced and should be cleaned up. You can associate data with a template instance, and you can access its DOM nodes when it is in the document.
Additionally, Meteor will maintain a template instance and its state
even if its surrounding HTML is re-rendered into new DOM nodes. As
long as the structure of template invocations is the same, Meteor will
not consider any instances to have been created or destroyed. You can
request that the same DOM nodes be retained as well using preserve
and constant
.
There are a number of callbacks and directives that you can specify on a named template and that apply to all instances of the template. They are described below.
Template.myTemplate([data]) Client
Call a template function by name to produce HTML.
Arguments
- data Object
Optional. The data context object with which to call the template.
When called inside a template helper, the body of Meteor.render
, or
other settings where reactive HTML is being generated, the resulting
HTML is annotated so that it renders as reactive DOM elements.
Otherwise, the HTML is unadorned and static.
Template.myTemplate.rendered = function ( ) { ... } Client
Provide a callback when an instance of a template is rendered.
This callback is called once when an instance of Template.myTemplate is rendered into DOM nodes and put into the document for the first time, and again each time any part of the template is re-rendered.
In the body of the callback, this
is a template
instance object that is unique to this occurrence of
the template and persists across re-renderings. Use the created
and
destroyed
callbacks to perform initialization or clean-up on the
object.
Template.myTemplate.created = function ( ) { ... } Client
Provide a callback when an instance of a template is created.
This callback is called when an invocation of myTemplate represents
a new occurrence of the template and not a re-rendering of an existing
template instance. Inside the callback, this
is the new template
instance object. Properties you set on this object
will be visible from the rendered
and destroyed
callbacks and from
event handlers.
This callback fires once and is the first callback to fire. Every
created
has a corresponding destroyed
; that is, if you get a
created
callback with a certain template instance object in this
,
you will eventually get a destroyed
callback for the same object.
Template.myTemplate.destroyed = function ( ) { ... } Client
Provide a callback when an instance of a template is destroyed.
This callback is called when an occurrence of a template is taken off
the page for any reason and not replaced with a re-rendering. Inside
the callback, this
is the template instance object
being destroyed.
This callback is most useful for cleaning up or undoing any external
effects of created
. It fires once and is the last callback to fire.
Template.myTemplate.events(eventMap) Client
Specify event handlers for this template.
Arguments
- eventMap Event map
Event handlers to associate with this template.
Declare event handers for instances of this template. Multiple calls add new event handlers in addition to the existing ones.
See Event Maps for a detailed description of the event map format and how event handling works in Meteor.
Template.myTemplate.helpers(helpers) Client
Specify template helpers available to this template.
Arguments
- helpers Object
Dictionary of helper functions by name.
Each template has a local dictionary of helpers that are made available to it, and this call specifies helpers to add to the template's dictionary.
Example:
Template.myTemplate.helpers({
foo: function () {
return Session.get("foo");
}
});
In Handlebars, this helper would then be invoked as {{foo}}
.
The following syntax is equivalent, but won't work for reserved property names:
Template.myTemplate.foo = function () {
return Session.get("foo");
};
Template.myTemplate.preserve(selectors) Client
Specify rules for preserving individual DOM elements on re-render.
Arguments
- selectors Array or Object
Array of CSS selectors that each match at most one element, such as
['.thing1', '.thing2']
, or, alternatively, a dictionary of selectors and node-labeling functions (see below).
You can "preserve" a DOM element during re-rendering, leaving the existing element in place in the document while replacing the surrounding HTML. This means that re-rendering a template need not disturb text fields, iframes, and other sensitive elements it contains. The elements to preserve must be present both as nodes in the old DOM and as tags in the new HTML. Meteor will patch the DOM around the preserved elements.
By default, new Meteor apps automatically include the
preserve-inputs
package. This preserves all elements of type
input
, textarea
, button
, select
, and option
that have unique
id
attributes or that have name
attributes that are unique within
an enclosing element with an id
attribute. To turn off this default
behavior, simply remove the preserve-inputs
package.
Preservation is useful in a variety of cases where replacing a DOM element with an identical or modified element would not have the same effect as retaining the original element. These include:
- Input text fields and other form controls
- Elements with CSS animations
- Iframes
- Nodes with references kept in JavaScript code
If you want to preserve a whole region of the DOM, an element and its children, or nodes not rendered by Meteor, use a constant region instead.
To preserve nodes, pass a list of selectors, each of which should match at most one element in the template. When the template is re-rendered, the selector is run on the old DOM and the new DOM, and Meteor will reuse the old element in place while working in any HTML changes around it.
A second form of preserve
takes a labeling function for each selector
and allows the selectors to match multiple nodes. The node-labeling
function takes a node and returns a label string that is unique for each
node, or false
to exclude the node from preservation.
For example, to preserve all <input>
elements with ids in template 'foo', use:
Template.foo.preserve({
'input[id]': function (node) { return node.id; }
});
Selectors are interpreted as rooted at the top level of the template. Each occurrence of the template operates independently, so the selectors do not have to be unique on the entire page, only within one occurrence of the template. Selectors will match nodes even if they are in sub-templates.
Preserving a node does not preserve its attributes or contents. They will be updated to reflect the new HTML. Text in input fields is not preserved unless the input field has focus, in which case the cursor and selection are left intact. Iframes retain their navigation state and animations continue to run as long as their parameters haven't changed.
There are some cases where nodes can not be preserved because of constraints inherent in the DOM API. For example, an element's tag name can't be changed, and it can't be moved relative to its parent or other preserved nodes. For this reason, nodes that are re-ordered or re-parented by an update will not be preserved.
Previous versions of Meteor had an implicit page-wide preserve
directive that labeled nodes by their "id" and "name" attributes.
This has been removed in favor of the explicit, opt-in mechanism.
Template instances
A template instance object represents an occurrence of a template in the document. It can be used to access the DOM and it can be assigned properties that persist across page re-renderings.
Template instance objects are found as the value of this
in the
created
, rendered
, and destroyed
template callbacks and as an
argument to event handlers.
In addition to the properties and functions described below, you can
assign additional properties of your choice to the object. Property names
starting with _
are guaranteed to be available for your use. Use
the created
and destroyed
callbacks to perform initialization or
clean-up on the object.
You can only access findAll
, find
, firstNode
, and lastNode
from the rendered
callback and event handlers, not from created
and destroyed
, because they require the template instance to be
in the DOM.
this.findAll(selector) Client
Find all elements matching selector
in this template instance.
Arguments
- selector String
The CSS selector to match, scoped to the template contents.
Returns an array of DOM elements matching selector
.
The template instance serves as the document root for the selector. Only elements inside the template and its sub-templates can match parts of the selector.
this.find(selector) Client
Find one element matching selector
in this template instance.
Arguments
- selector String
The CSS selector to match, scoped to the template contents.
Returns one DOM element matching selector
, or null
if there are no
such elements.
The template instance serves as the document root for the selector. Only elements inside the template and its sub-templates can match parts of the selector.
this.firstNode Client
The first top-level DOM node in this template instance.
The two nodes firstNode
and lastNode
indicate the extent of the
rendered template in the DOM. The rendered template includes these
nodes, their intervening siblings, and their descendents. These two
nodes are siblings (they have the same parent), and lastNode
comes
after firstNode
, or else they are the same node.
this.lastNode Client
The last top-level DOM node in this template instance.
this.data Client
The data context of this instance's latest invocation.
This property provides access to the data context at the top level of the template. It is updated each time the template is re-rendered. Access is read-only and non-reactive.
Meteor.render(htmlFunc) Client
Create DOM nodes that automatically update themselves as data changes.
Arguments
- htmlFunc Function returning a string of HTML
Function that generates HTML to be rendered. Called immediately and re-run whenever data changes. May also be a string of HTML instead of a function.
Meteor.render
creates a DocumentFragment
(a sequence of DOM nodes)
that automatically updates in realtime. Most Meteor apps don't need to
call this directly; they use templates and Meteor handles the rendering.
Pass in htmlFunc
, a function that returns an HTML
string. Meteor.render
calls the function and turns the output into
DOM nodes. Meanwhile, it tracks the data that was used when htmlFunc
ran, and automatically wires up callbacks so that whenever any of the
data changes, htmlFunc
is re-run and the DOM nodes are updated in
place.
You may insert the returned DocumentFragment
directly into the DOM
wherever you would like it to appear. The inserted nodes will continue
to update until they are taken off the screen. Then they will be
automatically cleaned up. For more details about clean-up, see
Deps.flush
.
Meteor.render
tracks the data dependencies of htmlFunc
by running
it in a reactive computation, so it can respond to changes in any reactive
data sources used by that function. For more information, or to learn
how to make your own reactive data sources, see
Reactivity.
Example:
// Client side: show the number of players online.
var frag = Meteor.render(function () {
return "<p>There are " + Players.find({online: true}).count() +
" players online.</p>";
});
document.body.appendChild(frag);
// Server side: find all players that have been idle for a while,