mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
some compatibility notes about packages:
- packages now have their own namespaces (rather than needing to
use the global namespace). symbols you want to share should
be declared with an @export comment
- this also means that missing dependencies can hurt you. so don't
leave them out.
- your app's packages (in the 'packages' directory in your app) are
not automatically included in your app; you need to explicitly
run "meteor add" for them. this means that, eg, you can have test
helper packages which are not directly used in your app, but just
used by other packages' tests. (before releasing this, we may
make 'meteor update' fix current apps.)
- the bundle ("star") format has changed
- packages are now built into the "unipackage" format. if this format changes
before we release this code (and commit to the definition of the initial
versions of the formats) you may need to run "meteor rebuild-all"
- __meteor_bootstrap__ has been stripped of everything not related to
executing JS code. Some of what used to be there is now on the WebApp
object.
more detailed docs are likely to come before the 0.6.5 release.
3028 lines
113 KiB
HTML
3028 lines
113 KiB
HTML
<template name="api">
|
|
{{#better_markdown}}
|
|
|
|
<h1 id="api">The Meteor API</h1>
|
|
|
|
Your JavaScript code can run in two environments: the *client* (browser), and
|
|
the *server* (a [Node.js](http://nodejs.org/) 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*.
|
|
|
|
<h2 id="core"><span>Meteor Core</span></h2>
|
|
|
|
{{> api_box isClient}}
|
|
{{> api_box isServer}}
|
|
{{> api_box 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 smart 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"});
|
|
}
|
|
});
|
|
}
|
|
|
|
{{> api_box absoluteUrl}}
|
|
|
|
{{> api_box settings}}
|
|
|
|
{{> api_box release}}
|
|
|
|
<h2 id="publishandsubscribe"><span>Publish and subscribe</span></h2>
|
|
|
|
These functions control how Meteor servers publish sets of records and
|
|
how clients can subscribe to those sets.
|
|
|
|
{{> api_box publish}}
|
|
|
|
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`](#meteor_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.
|
|
|
|
{{#warning}}
|
|
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.
|
|
{{/warning}}
|
|
|
|
// 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`](#publish_added) (when a new document is added to the published record
|
|
set), [`changed`](#publish_changed) (when some fields on a document in the
|
|
record set are changed or cleared), and [`removed`](#publish_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.
|
|
|
|
|
|
|
|
<!-- TODO discuss ready -->
|
|
|
|
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.");
|
|
|
|
{{#warning}}
|
|
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.
|
|
{{/warning}}
|
|
|
|
{{> api_box subscription_userId}}
|
|
|
|
This is constant. However, if the logged-in user changes, the publish
|
|
function is rerun with the new value.
|
|
|
|
{{> api_box subscription_added}}
|
|
{{> api_box subscription_changed}}
|
|
{{> api_box subscription_removed}}
|
|
{{> api_box subscription_ready}}
|
|
|
|
{{> api_box subscription_onStop}}
|
|
|
|
If you call [`observe`](#observe) or [`observeChanges`](#observe_changes) in your
|
|
publish handler, this is the place to stop the observes.
|
|
|
|
{{> api_box subscription_error}}
|
|
{{> api_box subscription_stop}}
|
|
|
|
{{> api_box subscribe}}
|
|
|
|
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](#meteor_collection), 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`](#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](#publish_ready). The `onError` callback is
|
|
called with a [`Meteor.Error`](#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:
|
|
|
|
<dl class="callbacks">
|
|
{{#dtdd "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.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "ready()"}}
|
|
True if the server has [marked the subscription as ready](#publish_ready). A
|
|
reactive data source.
|
|
{{/dtdd}}
|
|
</dl>
|
|
|
|
If you call `Meteor.subscribe` within a [reactive computation](#reactivity),
|
|
for example using
|
|
[`Deps.autorun`](#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.
|
|
|
|
<h2 id="methods_header"><span>Methods</span></h2>
|
|
|
|
Methods are remote functions that Meteor clients can invoke.
|
|
|
|
{{> api_box methods}}
|
|
|
|
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](#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`](#insert), [`update`](#update), [`remove`](#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.
|
|
|
|
{{> api_box method_invocation_userId}}
|
|
|
|
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](#accounts_api) then this is handled for you.
|
|
|
|
{{> api_box method_invocation_setUserId}}
|
|
|
|
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](#accounts_api) then this
|
|
should correspond to the `_id` field of a document in the
|
|
[`Meteor.users`](#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.
|
|
|
|
{{> api_box method_invocation_isSimulation}}
|
|
|
|
{{> api_box method_invocation_unblock}}
|
|
|
|
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.
|
|
|
|
{{> api_box error}}
|
|
|
|
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')`.
|
|
|
|
{{> api_box meteor_call}}
|
|
|
|
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`](#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).
|
|
|
|
{{> api_box meteor_apply}}
|
|
|
|
`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.
|
|
|
|
<h2 id="connections"><span>Server connections</span></h2>
|
|
|
|
These functions manage and inspect the network connection between the
|
|
Meteor client and server.
|
|
|
|
{{> api_box status}}
|
|
|
|
This method returns the status of the connection between the client and
|
|
the server. The return value is an object with the following fields:
|
|
|
|
<dl class="objdesc">
|
|
{{#dtdd name="connected" type="Boolean"}}
|
|
True if currently connected to the server. If false, changes and
|
|
method invocations will be queued up until the connection is
|
|
reestablished.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd name="status" type="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) and `waiting` (failed
|
|
to connect and waiting to try to reconnect).
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd name="retryCount" type="Number"}}
|
|
The number of times the client has tried to reconnect since the
|
|
connection was lost. 0 when connected.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd name="retryTime" type="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 when `status` is `waiting`.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd name="reason" type="String or undefined"}}
|
|
If `status` is `failed`, a description of why the connection failed.
|
|
{{/dtdd}}
|
|
</dl>
|
|
|
|
Instead of using callbacks to notify you on changes, this is
|
|
a [reactive](#reactivity) data source. You can use it in a
|
|
[template](#templates) or [computation](#deps_autorun)
|
|
to get realtime updates.
|
|
|
|
{{> api_box reconnect}}
|
|
|
|
{{> api_box connect}}
|
|
|
|
To call methods on another Meteor application or subscribe to its data
|
|
sets, call `Meteor.connect` with the URL of the application.
|
|
`Meteor.connect` returns an object which provides:
|
|
|
|
* `subscribe` -
|
|
Subscribe to a record set. See
|
|
[Meteor.subscribe](#meteor_subscribe).
|
|
* `call` -
|
|
Invoke a method. See [Meteor.call](#meteor_call).
|
|
* `apply` -
|
|
Invoke a method with an argument array. See
|
|
[Meteor.apply](#meteor_apply).
|
|
* `methods` -
|
|
Define client-only stubs for methods defined on the remote server. See
|
|
[Meteor.methods](#meteor_methods).
|
|
* `status` -
|
|
Get the current connection status. See
|
|
[Meteor.status](#meteor_status).
|
|
* `reconnect` -
|
|
See [Meteor.reconnect](#meteor_reconnect).
|
|
* `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.
|
|
|
|
{{#warning}}
|
|
In this release, `Meteor.connect` can only be called on the client.
|
|
Servers can not yet connect to other servers.
|
|
{{/warning}}
|
|
|
|
<h2 id="collections"><span>Collections</span></h2>
|
|
|
|
Meteor stores data in *collections*. To get started, declare a
|
|
collection with `new Meteor.Collection`.
|
|
|
|
{{> api_box meteor_collection}}
|
|
|
|
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`](#insert)
|
|
documents in the collection, [`update`](#update) their properties, and
|
|
[`remove`](#remove) them, and to [`find`](#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](#allow)).
|
|
|
|
* 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`](#find)) are served directly out of
|
|
this cache, without talking to the server.
|
|
|
|
* When you write to the database on the client ([`insert`](#insert),
|
|
[`update`](#update), [`remove`](#remove)), the command is executed
|
|
immediately on the client, and, simultaneously, it's shipped up to the
|
|
server and executed there too. The `livedata` 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`](#find), [`insert`](#insert),
|
|
[`update`](#update), and [`remove`](#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`](#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.
|
|
|
|
{{#warning}}
|
|
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.
|
|
{{/warning}}
|
|
|
|
{{#warning}}
|
|
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.
|
|
{{/warning}}
|
|
|
|
{{> api_box find}}
|
|
|
|
`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.
|
|
|
|
{{#warning}}
|
|
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.
|
|
{{/warning}}
|
|
|
|
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`](#deps_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`.
|
|
|
|
{{> api_box findone}}
|
|
|
|
Equivalent to `find(selector, options).fetch()[0]` with
|
|
`options.limit = 1`.
|
|
|
|
{{> api_box insert}}
|
|
|
|
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`](#allow) and [`deny`](#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"});
|
|
|
|
{{> api_box update}}
|
|
|
|
Modify documents that match `selector` according to `modifier` (see
|
|
[modifier documentation](#modifiers)).
|
|
|
|
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](#selectors) to find the documents to modify. It bypasses
|
|
any access control rules set up by [`allow`](#allow) and
|
|
[`deny`](#deny).
|
|
|
|
- Untrusted code can only modify a single document at once, specified
|
|
by its `_id`. The modification is allowed only after checking any
|
|
applicable [`allow`](#allow) and [`deny`](#deny) 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});
|
|
}
|
|
});
|
|
|
|
{{#warning}}
|
|
The Mongo `upsert` feature is not implemented.
|
|
{{/warning}}
|
|
|
|
{{> api_box remove}}
|
|
|
|
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](#selectors) 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`](#allow) and
|
|
[`deny`](#deny).
|
|
|
|
As a safety measure, if `selector` is omitted (or is `undefined`),
|
|
no documents will be removed. Set `selector` 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 applicable [`allow`](#allow) and [`deny`](#deny) 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}});
|
|
}
|
|
});
|
|
|
|
{{> api_box allow}}
|
|
|
|
When a client calls `insert`, `update`, or `remove` on a collection, the
|
|
collection's `allow` and [`deny`](#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:
|
|
|
|
<dl class="callbacks">
|
|
{{#dtdd "insert(userId, doc)"}}
|
|
The user `userId` wants to insert the document `doc` into the
|
|
collection. Return `true` if this should be allowed.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "update(userId, doc, fieldNames, modifier)"}}
|
|
|
|
The user `userId` wants to update a document `doc`. (`doc` is the
|
|
current version of the document from the database, without the
|
|
proposed update.) Return `true` to permit the change.
|
|
|
|
`fieldNames` is an array of the (top-level) fields in `doc` 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 the `allow`
|
|
functions.
|
|
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "remove(userId, doc)"}}
|
|
|
|
The user `userId` wants to remove `doc` from the database. Return
|
|
`true` to permit this.
|
|
|
|
{{/dtdd}}
|
|
|
|
</dl>
|
|
|
|
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`.
|
|
|
|
{{> api_box deny}}
|
|
|
|
This works just like [`allow`](#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`.
|
|
|
|
<h2 id="meteor_collection_cursor"><span>Cursors</span></h2>
|
|
|
|
To create a cursor, use [`find`](#find). To access the documents in a
|
|
cursor, use [`forEach`](#foreach), [`map`](#map), or [`fetch`](#fetch).
|
|
|
|
{{> api_box cursor_foreach}}
|
|
|
|
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;
|
|
});
|
|
|
|
{{> api_box cursor_map}}
|
|
|
|
When called from a reactive computation, `map` registers dependencies on
|
|
the matching documents.
|
|
|
|
<!-- The following is not yet implemented, but users shouldn't assume
|
|
sequential execution anyway because that will break. -->
|
|
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.
|
|
|
|
{{> api_box cursor_fetch}}
|
|
|
|
When called from a reactive computation, `fetch` registers dependencies on
|
|
the matching documents.
|
|
|
|
{{> api_box cursor_count}}
|
|
|
|
// 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.)
|
|
|
|
{{> api_box cursor_rewind}}
|
|
|
|
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.
|
|
|
|
{{> api_box cursor_observe}}
|
|
|
|
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`](#observe_changes).
|
|
|
|
`callbacks` may have the following functions as properties:
|
|
|
|
<dl class="callbacks">
|
|
<dt><span class="name">added(document)</span> <span class="or">or</span></dt>
|
|
<dt><span class="name">addedAt(document, atIndex, before)</span></dt>
|
|
<dd>
|
|
{{#better_markdown}}
|
|
A new document `document` entered the result set. The new document
|
|
appears at position `atIndex`. It is immediately before the document
|
|
whose `_id` is `before`. `before` will be `null` if the new document
|
|
is at the end of the results.
|
|
{{/better_markdown}}
|
|
</dd>
|
|
|
|
<dt><span class="name">changed(newDocument, oldDocument)
|
|
<span class="or">or</span></span></dt>
|
|
<dt><span class="name">changedAt(newDocument, oldDocument, atIndex)</span></dt>
|
|
<dd>
|
|
{{#better_markdown}}
|
|
The contents of a document were previously `oldDocument` and are now
|
|
`newDocument`. The position of the changed document is `atIndex`.
|
|
{{/better_markdown}}
|
|
</dd>
|
|
|
|
<dt><span class="name">removed(oldDocument)</span>
|
|
<span class="or">or</span></dt>
|
|
<dt><span class="name">removedAt(oldDocument, atIndex)</span></dt>
|
|
<dd>
|
|
{{#better_markdown}}
|
|
The document `oldDocument` is no longer in the result set. It used to be at position `atIndex`.
|
|
{{/better_markdown}}
|
|
</dd>
|
|
|
|
{{#dtdd "movedTo(document, fromIndex, toIndex, before)"}}
|
|
A document changed its position in the result set, from `fromIndex` to `toIndex`
|
|
(which is before the document with id `before`). Its current contents is
|
|
`document`.
|
|
{{/dtdd}}
|
|
</dl>
|
|
|
|
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.)
|
|
|
|
|
|
{{> api_box cursor_observe_changes}}
|
|
|
|
Establishes a *live query* that invokes callbacks when the result of
|
|
the query changes. In contrast to [`observe`](#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:
|
|
|
|
<dl class="callbacks">
|
|
<dt><span class="name">added(id, fields)</span>
|
|
<span class="or">or</span></dt>
|
|
<dt><span class="name">addedBefore(id, fields, before)</span></dt>
|
|
<dd>
|
|
{{#better_markdown}}
|
|
A new document entered the result set. It has the `id` and `fields`
|
|
specified. `fields` contains all fields of the document excluding the
|
|
`_id` field. The new document is before the document identified by
|
|
`before`, or at the end if `before` is `null`.
|
|
{{/better_markdown}}
|
|
</dd>
|
|
|
|
{{#dtdd "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 in `fields` with a value of
|
|
`undefined`.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "movedBefore(id, before)"}}
|
|
The document identified by `id` changed its position in the ordered result set,
|
|
and now appears before the document identified by `before`.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "removed(id)"}}
|
|
The document identified by `id` was removed from the result set.
|
|
{{/dtdd}}
|
|
</dl>
|
|
|
|
`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.)
|
|
|
|
{{#note}}
|
|
Unlike `observe`, `observeChanges` does not provide absolute position
|
|
information (that is, `atIndex` positions rather than `before`
|
|
positions.) This is for efficiency.
|
|
{{/note}}
|
|
|
|
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);
|
|
|
|
{{> api_box collection_object_id}}
|
|
|
|
`Meteor.Collection.ObjectID` follows the same API as the [Node MongoDB driver
|
|
`ObjectID`](http://mongodb.github.com/node-mongodb-native/api-bson-generated/objectid.html)
|
|
class. Note that you must use the `equals` method (or [`EJSON.equals`](#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`](#ejson_equals) instead of `===` to compare them.
|
|
|
|
{{#note}}
|
|
`ObjectID` values created by Meteor will not have meaningful answers to their `getTimestamp`
|
|
method, since Meteor currently constructs them fully randomly.
|
|
{{/note}}
|
|
|
|
{{#api_box_inline selectors}}
|
|
|
|
In its simplest form, a selector is just a set of keys that must
|
|
match in a document:
|
|
|
|
// Matches all documents where deleted is false
|
|
{deleted: false}
|
|
|
|
// Matches all documents where the name and cognomen are as given
|
|
{name: "Rhialto", cognomen: "the Marvelous"}
|
|
|
|
// Matches every document
|
|
{}
|
|
|
|
But they can also contain more complicated tests:
|
|
|
|
// Matches documents where age is greater than 18
|
|
{age: {$gt: 18}}
|
|
|
|
// Also matches documents where tags is an array containing "popular"
|
|
{tags: "popular"}
|
|
|
|
// Matches documents where fruit is one of three possibilities
|
|
{fruit: {$in: ["peach", "plum", "pear"]}}
|
|
|
|
See the [complete
|
|
documentation](http://www.mongodb.org/display/DOCS/Advanced+Queries).
|
|
|
|
{{/api_box_inline}}
|
|
|
|
{{#api_box_inline modifiers}}
|
|
|
|
A modifier is an object that describes how to update a document in
|
|
place by changing some of its fields. Some examples:
|
|
|
|
// Set the 'admin' property on the document to true
|
|
{$set: {admin: true}}
|
|
|
|
// Add 2 to the 'votes' property, and add "Traz"
|
|
// to the end of the 'supporters' array
|
|
{$inc: {votes: 2}, $push: {supporters: "Traz"}}
|
|
|
|
But if a modifier doesn't contain any $-operators, then it is instead
|
|
interpreted as a literal document, and completely replaces whatever was
|
|
previously in the database. (Literal document modifiers are not currently
|
|
supported by [validated updates](#allow).)
|
|
|
|
// Find the document with id "123", and completely replace it.
|
|
Users.update({_id: "123"}, {name: "Alice", friends: ["Bob"]});
|
|
|
|
See the [full list of
|
|
modifiers](http://www.mongodb.org/display/DOCS/Updating#Updating-ModifierOperations).
|
|
|
|
{{/api_box_inline}}
|
|
|
|
{{#api_box_inline sortspecifiers}}
|
|
|
|
Sorts may be specified using your choice of several syntaxes:
|
|
|
|
// All of these do the same thing (sort in ascending order by
|
|
// key "a", breaking ties in descending order of key "b")
|
|
|
|
[["a", "asc"], ["b", "desc"]]
|
|
["a", ["b", "desc"]]
|
|
{a: 1, b: -1}
|
|
|
|
The last form will only work if your JavaScript implementation
|
|
preserves the order of keys in objects. Most do, most of the time, but
|
|
it's up to you to be sure.
|
|
|
|
{{/api_box_inline}}
|
|
|
|
{{#api_box_inline fieldspecifiers}}
|
|
|
|
On the server, queries can specify a particular set of fields to include
|
|
or exclude from the result object. (The field specifier is currently
|
|
ignored on the client.)
|
|
|
|
To exclude certain fields from the result objects, the field specifier
|
|
is a dictionary whose keys are field names and whose values are `0`.
|
|
|
|
// Users.find({}, {fields: {password: 0, hash: 0}})
|
|
|
|
To return an object that only includes the specified field, use `1` as
|
|
the value. The `_id` field is still included in the result.
|
|
|
|
// Users.find({}, {fields: {firstname: 1, lastname: 1}})
|
|
|
|
It is not possible to mix inclusion and exclusion styles.
|
|
|
|
{{/api_box_inline}}
|
|
|
|
<h2 id="session"><span>Session</span></h2>
|
|
|
|
`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`](#session_get)`("currentList")`
|
|
from inside a template, the template will automatically be rerendered
|
|
whenever [`Session.set`](#session_set)`("currentList", x)` is called.
|
|
|
|
{{> api_box set}}
|
|
|
|
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");
|
|
|
|
{{> api_box setDefault}}
|
|
|
|
This is useful in initialization code, to avoid re-initializing a session
|
|
variable every time a new version of your app is loaded.
|
|
|
|
{{> api_box get}}
|
|
|
|
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");
|
|
|
|
{{> api_box equals}}
|
|
|
|
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">
|
|
{{dstache}}! 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. }}
|
|
|
|
{{dstache}}#each posts}}
|
|
{{dstache}}> postItem }}
|
|
{{dstache}}/each}}
|
|
</{{! }}template>
|
|
|
|
<template name="postItem">
|
|
<div class="{{dstache}}postClass}}">{{dstache}}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)`.
|
|
|
|
|
|
|
|
<h2 id="accounts_api"><span>Accounts</span></h2>
|
|
|
|
The Meteor Accounts system builds on top of the `userId` support in
|
|
[`publish`](#publish_userId) and [`methods`](#method_userId). The core
|
|
packages add the concept of user documents stored in the database, and
|
|
additional packages add [secure password
|
|
authentication](#accounts_passwords), [integration with third party
|
|
login services](#meteor_loginwithexternalservice), and a [pre-built user
|
|
interface](#accountsui).
|
|
|
|
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`.
|
|
|
|
|
|
{{> api_box user}}
|
|
|
|
Retrieves the user record for the current user from
|
|
the [`Meteor.users`](#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`](#meteor_users) for more on
|
|
the fields used in user documents.
|
|
|
|
{{> api_box userId}}
|
|
|
|
{{> api_box users}}
|
|
|
|
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: "cool@example.com", verified: true },
|
|
{ address: "another@different.com", verified: false }
|
|
],
|
|
createdAt: 1349761684042,
|
|
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: 1349761684048 }
|
|
]
|
|
}
|
|
}
|
|
}
|
|
|
|
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 keys `address` and `verified`;
|
|
an email address may belong to at most one user. `verified` is
|
|
a Boolean which is true if the user has [verified the
|
|
address](#accounts_verifyemail) 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, its `reset` field contains
|
|
tokens used by [forgot password](#accounts_forgotpassword) links,
|
|
and its `resume` field contains tokens used to keep you
|
|
logged in between sessions.
|
|
|
|
Like all [Meteor.Collection](#collections)s, 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`](#accounts_createuser) and modify it with
|
|
`Meteor.users.update`. To allow users to edit additional fields, use
|
|
[`Meteor.users.allow`](#allow). To forbid users from making any modifications to
|
|
their user document:
|
|
|
|
Meteor.users.deny({update: function () { return true; }});
|
|
|
|
|
|
{{> api_box loggingIn}}
|
|
|
|
For example, [the `accounts-ui` package](#accountsui) uses this to display an
|
|
animation while the login request is being processed.
|
|
|
|
{{> api_box logout}}
|
|
|
|
{{> api_box loginWithPassword}}
|
|
|
|
This function is provided by the `accounts-password` package. See the
|
|
[Passwords](#accounts_passwords) section below.
|
|
|
|
|
|
{{> api_box loginWithExternalService}}
|
|
|
|
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.
|
|
|
|
<a id="requestpermissions" name="requestpermissions" />
|
|
|
|
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](#accountsui) 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');
|
|
});
|
|
|
|
|
|
|
|
{{> api_box currentUser}}
|
|
{{> api_box loggingInTemplate}}
|
|
{{> api_box accounts_config}}
|
|
{{> api_box accounts_ui_config}}
|
|
|
|
Example:
|
|
|
|
Accounts.ui.config({
|
|
requestPermissions: {
|
|
facebook: ['user_likes'],
|
|
github: ['user', 'repo']
|
|
},
|
|
requestOfflineToken: {
|
|
google: true
|
|
},
|
|
passwordSignupFields: 'USERNAME_AND_OPTIONAL_EMAIL'
|
|
});
|
|
|
|
{{> api_box accounts_validateNewUser}}
|
|
|
|
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`](#accountsui)), throw a new
|
|
[`Meteor.Error`](#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";
|
|
});
|
|
|
|
{{> api_box accounts_onCreateUser}}
|
|
|
|
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`](#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`](#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:
|
|
|
|
<!-- XXX replace d6 with _.random once we have underscore 1.4.2 -->
|
|
|
|
// 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;
|
|
});
|
|
|
|
|
|
<h2 id="accounts_passwords"><span>Passwords</span></h2>
|
|
|
|
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](http://en.wikipedia.org/wiki/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](#accountsui) to
|
|
include a turn-key user interface for password-based sign-in.
|
|
|
|
|
|
{{> api_box accounts_createUser}}
|
|
|
|
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`](#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`](#accounts_oncreateuser).
|
|
|
|
This function is only used for creating users with passwords. The external
|
|
service login flows do not use this function.
|
|
|
|
|
|
{{> api_box accounts_changePassword}}
|
|
|
|
{{> api_box accounts_forgotPassword}}
|
|
|
|
This triggers a call
|
|
to [`Accounts.sendResetPasswordEmail`](#accounts_sendresetpasswordemail)
|
|
on the server. Pass the token the user receives in this email
|
|
to [`Accounts.resetPassword`](#accounts_resetpassword) to
|
|
complete the password reset process.
|
|
|
|
If you are using the [`accounts-ui` package](#accountsui), this is handled
|
|
automatically. Otherwise, it is your responsiblity to prompt the user for the
|
|
new password and call `resetPassword`.
|
|
|
|
{{> api_box accounts_resetPassword}}
|
|
|
|
This function accepts tokens generated
|
|
by [`Accounts.sendResetPasswordEmail`](#accounts_sendresetpasswordemail)
|
|
and
|
|
[`Accounts.sendEnrollmentEmail`](#accounts_sendenrollmentemail).
|
|
|
|
{{> api_box accounts_setPassword}}
|
|
|
|
{{> api_box accounts_verifyEmail}}
|
|
|
|
This function accepts tokens generated
|
|
by [`Accounts.sendVerificationEmail`](#accounts_sendverificationemail). It
|
|
sets the `emails.verified` field in the user record.
|
|
|
|
{{> api_box accounts_sendResetPasswordEmail}}
|
|
|
|
The token in this email should be passed
|
|
to [`Accounts.resetPassword`](#accounts_resetpassword).
|
|
|
|
To customize the contents of the email, see
|
|
[`Accounts.emailTemplates`](#accounts_emailtemplates).
|
|
|
|
{{> api_box accounts_sendEnrollmentEmail}}
|
|
|
|
The token in this email should be passed
|
|
to [`Accounts.resetPassword`](#accounts_resetpassword).
|
|
|
|
To customize the contents of the email, see
|
|
[`Accounts.emailTemplates`](#accounts_emailtemplates).
|
|
|
|
{{> api_box accounts_sendVerificationEmail}}
|
|
|
|
The token in this email should be passed
|
|
to [`Accounts.verifyEmail`](#accounts_verifyemail).
|
|
|
|
To customize the contents of the email, see
|
|
[`Accounts.emailTemplates`](#accounts_emailtemplates).
|
|
|
|
{{> api_box accounts_emailTemplates}}
|
|
|
|
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`: A `String` with an [RFC5322](http://tools.ietf.org/html/rfc5322) From
|
|
address. By default, the email is sent from `no-reply@meteor.com`. 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`: An `Object` with two fields:
|
|
- `resetPassword.subject`: A `Function` that takes a user object and returns
|
|
a `String` for the subject line of a reset password email.
|
|
- `resetPassword.text`: A `Function` that takes a user object and a url, and
|
|
returns the body text for a reset password email.
|
|
- `enrollAccount`: Same as `resetPassword`, but for initial password setup for
|
|
new accounts.
|
|
- `verifyEmail`: Same as `resetPassword`, but for verifying the users email
|
|
address.
|
|
|
|
|
|
Example:
|
|
|
|
Accounts.emailTemplates.siteName = "AwesomeSite";
|
|
Accounts.emailTemplates.from = "AwesomeSite Admin <accounts@example.com>";
|
|
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;
|
|
};
|
|
|
|
|
|
<h2 id="templates_api"><span>Templates</span></h2>
|
|
|
|
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.
|
|
|
|
{{> api_box template_call}}
|
|
|
|
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.
|
|
|
|
|
|
{{> api_box template_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](#template_inst) 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.
|
|
|
|
{{> api_box template_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](#template_inst) 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.
|
|
|
|
{{> api_box template_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](#template_inst) 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.
|
|
|
|
|
|
{{> api_box template_events}}
|
|
|
|
Declare event handers for instances of this template. Multiple calls add
|
|
new event handlers in addition to the existing ones.
|
|
|
|
See [Event Maps](#eventmaps) for a detailed description of the event
|
|
map format and how event handling works in Meteor.
|
|
|
|
{{> api_box template_helpers}}
|
|
|
|
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 `{{dstache}}foo}}`.
|
|
|
|
The following syntax is equivalent, but won't work for reserved property
|
|
names:
|
|
|
|
Template.myTemplate.foo = function () {
|
|
return Session.get("foo");
|
|
};
|
|
|
|
{{> api_box template_preserve}}
|
|
|
|
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.
|
|
|
|
{{#note}}
|
|
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.
|
|
{{/note}}
|
|
|
|
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](#constant) 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.
|
|
|
|
{{#note}}
|
|
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.
|
|
{{/note}}
|
|
|
|
|
|
<h2 id="template_inst"><span>Template instances</span></h2>
|
|
|
|
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.
|
|
|
|
{{> api_box template_findAll}}
|
|
|
|
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.
|
|
|
|
{{> api_box template_find}}
|
|
|
|
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.
|
|
|
|
{{> api_box template_firstNode}}
|
|
|
|
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.
|
|
|
|
{{> api_box template_lastNode}}
|
|
|
|
{{> api_box template_data}}
|
|
|
|
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.
|
|
|
|
|
|
{{> api_box render}}
|
|
|
|
`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`](#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](#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,
|
|
// and mark them as offline. The count on the screen will
|
|
// automatically update on all clients.
|
|
Players.update({idleTime: {$gt: 30}}, {$set: {online: false}});
|
|
|
|
{{> api_box renderList}}
|
|
|
|
Creates a `DocumentFragment` that automatically updates as the results
|
|
of a database query change. Most Meteor apps use `{{dstache}}#each}}` in
|
|
a template instead of calling this directly.
|
|
|
|
`renderList` is more efficient than using `Meteor.render` to render HTML
|
|
for a list of documents. For example, if a new document is created in
|
|
the database that matches the query, a new item will be rendered and
|
|
inserted at the appropriate place in the DOM without re-rendering the
|
|
other elements. Similarly, if a document changes position in a sorted
|
|
query, the DOM nodes will simply be moved and not re-rendered.
|
|
|
|
`docFunc` is called as needed to generate HTML for each document. If
|
|
you provide `elseFunc`, then whenever the query returns no results, it
|
|
will be called to render alternate content. You might use this to show
|
|
a message like "No records match your query."
|
|
|
|
Each call to `docFunc` or `elseFunc` is run in its own reactive
|
|
computation so that if it has other external data dependencies, it will be
|
|
individually re-run when the data changes.
|
|
|
|
Example:
|
|
|
|
// List the titles of all of the posts that have the tag
|
|
// "frontpage". Keep the list updated as new posts are made, as tags
|
|
// change, etc. Display the selected post differently.
|
|
var frag = Meteor.renderList(
|
|
Posts.find({tags: "frontpage"}),
|
|
function(post) {
|
|
var style = Session.equals("selectedId", post._id) ? "selected" : "";
|
|
// A real app would need to quote/sanitize post.name
|
|
return '<div class="' + style + '">' + post.name + '</div>';
|
|
});
|
|
document.body.appendChild(frag);
|
|
|
|
// Select a post. This will cause only the selected item and the
|
|
// previously selected item to update.
|
|
var somePost = Posts.findOne({tags: "frontpage"});
|
|
Session.set("selectedId", somePost._id);
|
|
|
|
|
|
{{#api_box_inline eventmaps}}
|
|
|
|
Several functions take event maps. An event map is an object where
|
|
the properties specify a set of events to handle, and the values are
|
|
the handlers for those events. The property can be in one of several
|
|
forms:
|
|
|
|
<dl>
|
|
{{#dtdd "<em>eventtype</em>"}}
|
|
Matches a particular type of event, such as 'click'.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "<em>eventtype selector</em>"}}
|
|
Matches a particular type of event, but only when it appears on
|
|
an element that matches a certain CSS selector.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "<em>event1, event2</em>"}}
|
|
To handle more than one type of event with the same function, use a
|
|
comma-separated list.
|
|
{{/dtdd}}
|
|
</dl>
|
|
|
|
The handler function receives two arguments: `event`, an object with
|
|
information about the event, and `template`, a [template
|
|
instance](#template_inst) for the template where the handler is
|
|
defined. The handler also receives some additional context data in
|
|
`this`, depending on the context of the current element handling the
|
|
event. In a Handlebars template, an element's context is the
|
|
Handlebars data context where that element occurs, which is set by
|
|
block helpers such as `#with` and `#each`.
|
|
|
|
Example:
|
|
|
|
{
|
|
// Fires when any element is clicked
|
|
'click': function (event) { ... },
|
|
|
|
// Fires when any element with the 'accept' class is clicked
|
|
'click .accept': function (event) { ... },
|
|
|
|
// Fires when 'accept' is clicked, or a key is pressed
|
|
'keydown, click .accept': function (event) { ... }
|
|
}
|
|
|
|
Most events bubble up the document tree from their originating
|
|
element. For example, `'click p'` catches a click anywhere in a
|
|
paragraph, even if the click originated on a link, span, or some other
|
|
element inside the paragraph. The originating element of the event
|
|
is available as the `target` property, while the element that matched
|
|
the selector and is currently handling it is called `currentTarget`.
|
|
|
|
{
|
|
'click p': function (event) {
|
|
var paragraph = event.currentTarget; // always a P
|
|
var clickedElement = event.target; // could be the P or a child element
|
|
}
|
|
}
|
|
|
|
If a selector matches multiple elements that an event bubbles to, it
|
|
will be called multiple times, for example in the case of `'click
|
|
div'` or `'click *'`. If no selector is given, the handler
|
|
will only be called once, on the original target element.
|
|
|
|
The following properties and methods are available on the event object
|
|
passed to handlers:
|
|
|
|
<dl class="objdesc">
|
|
{{#dtdd name="type" type="String"}}
|
|
The event's type, such as "click", "blur" or "keypress".
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd name="target" type="DOM Element"}}
|
|
The element that originated the event.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd name="currentTarget" type="DOM Element"}}
|
|
The element currently handling the event. This is the element that
|
|
matched the selector in the event map. For events that bubble, it may
|
|
be `target` or an ancestor of `target`, and its value changes as the
|
|
event bubbles.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd name="which" type="Number"}}
|
|
For mouse events, the number of the mouse button (1=left, 2=middle, 3=right).
|
|
For key events, a character or key code.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "stopPropagation()"}}
|
|
Prevent the event from propagating (bubbling) up to other elements.
|
|
Other event handlers matching the same element are still fired, in
|
|
this and other event maps.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "stopImmediatePropagation()"}}
|
|
Prevent all additional event handlers from being run on this event,
|
|
including other handlers in this event map, handlers reached by
|
|
bubbling, and handlers in other event maps.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "preventDefault()"}}
|
|
Prevents the action the browser would normally take in response to this
|
|
event, such as following a link or submitting a form. Further handlers
|
|
are still called, but cannot reverse the effect.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "isPropagationStopped()"}}
|
|
Returns whether `stopPropagation()` has been called for this event.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "isImmediatePropagationStopped()"}}
|
|
Returns whether `stopImmediatePropagation()` has been called for this event.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "isDefaultPrevented()"}}
|
|
Returns whether `preventDefault()` has been called for this event.
|
|
{{/dtdd}}
|
|
</dl>
|
|
|
|
Returning `false` from a handler is the same as calling
|
|
both `stopImmediatePropagation` and `preventDefault` on the event.
|
|
|
|
Event types and their uses include:
|
|
|
|
<dl class="objdesc">
|
|
{{#dtdd "<code>click</code>"}}
|
|
Mouse click on any element, including a link, button, form control, or div.
|
|
Use `preventDefault()` to prevent a clicked link from being followed.
|
|
Some ways of activating an element from the keyboard also fire `click`.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "<code>dblclick</code>"}}
|
|
Double-click.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "<code>focus, blur</code>"}}
|
|
A text input field or other form control gains or loses focus. You
|
|
can make any element focusable by giving it a `tabindex` property.
|
|
Browsers differ on whether links, checkboxes, and radio buttons are
|
|
natively focusable. These events do not bubble.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "<code>change</code>"}}
|
|
A checkbox or radio button changes state. For text fields, use
|
|
`blur` or key events to respond to changes.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "<code>mouseenter, mouseleave</code>"}} The pointer enters or
|
|
leaves the bounds of an element. These events do not bubble.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "<code>mousedown, mouseup</code>"}}
|
|
The mouse button is newly down or up.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "<code>keydown, keypress, keyup</code>"}}
|
|
The user presses a keyboard key. `keypress` is most useful for
|
|
catching typing in text fields, while `keydown` and `keyup` can be
|
|
used for arrow keys or modifier keys.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "<code>tap</code>"}} Tap on an element. On touch-enabled
|
|
devices, this is a replacement to `click` that fires immediately.
|
|
These events are synthesized from `touchmove` and `touchend`.
|
|
{{/dtdd}}
|
|
|
|
</dl>
|
|
|
|
Other DOM events are available as well, but for the events above,
|
|
Meteor has taken some care to ensure that they work uniformly in all
|
|
browsers.
|
|
|
|
{{/api_box_inline}}
|
|
|
|
|
|
|
|
{{#api_box_inline constant}}
|
|
|
|
You can mark a region of a template as "constant" and not subject to
|
|
re-rendering using the
|
|
`{{dstache}}#constant}}...{{dstache}}/constant}}` block helper.
|
|
Content inside the `#constant` block helper is preserved exactly as-is
|
|
even if the enclosing template is re-rendered. Changes to other parts
|
|
of the template are patched in around it in the same manner as
|
|
`preserve`. Unlike individual node preservation, a constant region
|
|
retains not only the identities of its nodes but also their attributes
|
|
and contents. The contents of the block will only be evaluated once
|
|
per occurrence of the enclosing template.
|
|
|
|
Constant regions allow non-Meteor content to be embedded in a Meteor
|
|
template. Many third-party widgets create and manage their own DOM
|
|
nodes programmatically. Typically, you put an empty element in your
|
|
template, which the widget or library will then populate with
|
|
children. Normally, when Meteor re-renders the enclosing template it
|
|
would remove the new children, since the template says it should be
|
|
empty. If the container is wrapped in a `#constant` block, however, it
|
|
is left alone; whatever content is currently in the DOM remains.
|
|
|
|
{{#note}}
|
|
Constant regions are intended for embedding non-Meteor content.
|
|
Event handlers and reactive dependencies don't currently work
|
|
correctly inside constant regions.
|
|
{{/note}}
|
|
|
|
|
|
{{/api_box_inline}}
|
|
|
|
{{#api_box_inline isolate}}
|
|
|
|
Each template runs as its own reactive computation. When the template
|
|
accesses a reactive data source, such as by calling `Session.get` or
|
|
making a database query, this establishes a data dependency that will
|
|
cause the whole template to be re-rendered when the data changes.
|
|
This means that the amount of re-rendering for a particular change
|
|
is affected by how you've divided your HTML into templates.
|
|
|
|
Typically, the exact extent of re-rendering is not crucial, but if you
|
|
want more control, such as for performance reasons, you can use the
|
|
`{{dstache}}#isolate}}...{{dstache}}/isolate}}` helper. Data
|
|
dependencies established inside an `#isolate` block are localized to
|
|
the block and will not in themselves cause the parent template to be
|
|
re-rendered. This block helper essentially conveys the reactivity
|
|
benefits you would get by pulling the content out into a new
|
|
sub-template.
|
|
|
|
{{/api_box_inline}}
|
|
|
|
<h2 id="match"><span>Match</span></h2>
|
|
|
|
Meteor methods and publish functions take arbitrary [EJSON](#ejson) types as
|
|
arguments, but most arguments are expected to be of a particular type. Meteor's
|
|
`check` package is a lightweight library for checking that arguments and other
|
|
values are of the expected type. For example:
|
|
|
|
Meteor.publish("chats-in-room", function (roomId) {
|
|
// Make sure roomId is a string, not an arbitrary mongo selector object.
|
|
check(roomId, String);
|
|
return Chats.find({room: roomId});
|
|
});
|
|
|
|
Meteor.methods({addChat: function (roomId, message) {
|
|
check(roomId, String);
|
|
check(message, {
|
|
text: String,
|
|
timestamp: Date,
|
|
// Optional, but if present must be an array of strings.
|
|
tags: Match.Optional([String])
|
|
});
|
|
|
|
// ... do something with the message ...
|
|
}});
|
|
|
|
{{> api_box check}}
|
|
|
|
If the match fails, `check` throws a `Match.Error` describing how it failed. If
|
|
this error gets sent over the wire to the client, it will appear only as
|
|
`Meteor.Error(400, "Match Failed")`; the failure details will be written to the
|
|
server logs but not revealed to the client.
|
|
|
|
{{> api_box match_test}}
|
|
|
|
{{#api_box_inline matchpatterns}}
|
|
|
|
The following patterns can be used as pattern arguments to `check` and `Match.test`:
|
|
|
|
|
|
<dl>
|
|
{{#dtdd "<code>Match.Any</code>"}}
|
|
Matches any value.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "<code>String</code>, <code>Number</code>, <code>Boolean</code>, <code>undefined</code>, <code>null</code>"}}
|
|
Matches a primitive of the given type.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "<code>[<em>pattern</em>]</code>"}}
|
|
A one-element array matches an array of elements, each of which match
|
|
*pattern*. For example, `[Number]` matches a (possibly empty) array of numbers;
|
|
`[Match.Any]` matches any array.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "<code>{<em>key1</em>: <em>pattern1</em>, <em>key2</em>: <em>pattern2</em>, ...}</code>"}}
|
|
Matches an Object with the given keys, with values matching the given patterns.
|
|
If any *pattern* is a `Match.Optional`, that key does not need to exist
|
|
in the object. The value may not contain any keys not listed in the pattern.
|
|
The value must be a plain Object with no special prototype.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "<code>Match.ObjectIncluding({<em>key1</em>: <em>pattern1</em>, <em>key2</em>: <em>pattern2</em>, ...})</code>"}}
|
|
Matches an Object with the given keys; the value may also have other keys
|
|
with arbitrary values.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "<code>Object</code>"}}
|
|
Matches any plain Object with any keys; equivalent to
|
|
`Match.ObjectIncluding({})`.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "<code>Match.Optional(<em>pattern</em>)</code>"}}
|
|
Matches either `undefined` or something that matches *pattern*.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "<code>Match.OneOf(<em>pattern1</em>, <em>pattern2</em>, ...)</code>"}}
|
|
Matches any value that matches at least one of the provided patterns.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "Any constructor function (eg, <code>Date</code>)"}}
|
|
Matches any element that is an instance of that type.
|
|
{{/dtdd}}
|
|
|
|
{{#dtdd "<code>Match.Where(<em>condition</em>)</code>"}}
|
|
Calls the function *condition* with the value as the argument. If *condition*
|
|
returns true, this matches. If *condition* throws a `Match.Error` or returns
|
|
false, this fails. If *condition* throws any other error, that error is thrown
|
|
from the call to `check` or `Match.test`. Examples:
|
|
|
|
check(buffer, Match.Where(EJSON.isBinary));
|
|
|
|
NonEmptyString = Match.Where(function (x) {
|
|
check(x, String);
|
|
return x.length > 0;
|
|
}
|
|
check(arg, NonEmptyString);
|
|
{{/dtdd}}
|
|
</dl>
|
|
|
|
{{/api_box_inline}}
|
|
|
|
<h2 id="timers"><span>Timers</span></h2>
|
|
|
|
Meteor uses global environment variables
|
|
to keep track of things like the current request's user. To make sure
|
|
these variables have the right values, you need to use
|
|
`Meteor.setTimeout` instead of `setTimeout` and `Meteor.setInterval`
|
|
instead of `setInterval`.
|
|
|
|
These functions work just like their native JavaScript equivalents.
|
|
You'll get an error if you call the native function.
|
|
|
|
{{> api_box setTimeout}}
|
|
|
|
Returns a handle that can be used by `Meteor.clearTimeout`.
|
|
|
|
{{> api_box setInterval}}
|
|
|
|
Returns a handle that can be used by `Meteor.clearInterval`.
|
|
|
|
{{> api_box clearTimeout}}
|
|
{{> api_box clearInterval}}
|
|
|
|
<h2 id="deps"><span>Deps</span></h2>
|
|
|
|
Meteor has a simple dependency tracking system which allows it to
|
|
automatically rerun templates and other computations whenever
|
|
[`Session`](#session) variables, database queries, and other data
|
|
sources change.
|
|
|
|
Unlike most other systems, you don't have to manually declare these
|
|
dependencies — it "just works". The mechanism is simple and
|
|
efficient. When you call a function that supports reactive updates
|
|
(such as a database query), it automatically saves the current
|
|
Computation object, if any (representing, for example, the current
|
|
template being rendered). Later, when the data changes, the function
|
|
can "invalidate" the Computation, causing it to rerun (rerendering the
|
|
template).
|
|
|
|
Applications will find [`Deps.autorun`](#deps_autorun) useful, while more
|
|
advanced facilities such as `Deps.Dependency` and `onInvalidate`
|
|
callbacks are intended primarily for package authors implementing new
|
|
reactive data sources.
|
|
|
|
{{> api_box deps_autorun }}
|
|
|
|
`Deps.autorun` allows you to run a function that depends on reactive data
|
|
sources, in such a way that if there are changes to the data later,
|
|
the function will be rerun.
|
|
|
|
For example, you can monitor a cursor (which is a reactive data
|
|
source) and aggregate it into a session variable:
|
|
|
|
Deps.autorun(function () {
|
|
var oldest = _.max(Monkeys.find().fetch(), function (monkey) {
|
|
return monkey.age;
|
|
});
|
|
if (oldest)
|
|
Session.set("oldest", oldest.name);
|
|
});
|
|
|
|
Or you can wait for a session variable to have a certain value, and do
|
|
something the first time it does, calling `stop` on the computation to
|
|
prevent further rerunning:
|
|
|
|
Deps.autorun(function (c) {
|
|
if (! Session.equals("shouldAlert", true))
|
|
return;
|
|
|
|
c.stop();
|
|
alert("Oh no!");
|
|
});
|
|
|
|
The function is invoked immediately, at which point it may alert and
|
|
stop right away if `shouldAlert` is already true. If not, the
|
|
function is run again when `shouldAlert` becomes true.
|
|
|
|
A change to a data dependency does not cause an immediate rerun, but
|
|
rather "invalidates" the computation, causing it to rerun the next
|
|
time a flush occurs. A flush will occur automatically as soon as
|
|
the system is idle if there are invalidated computations. You can
|
|
also use [`Deps.flush`](#deps_flush) to cause an immediate flush of
|
|
all pending reruns.
|
|
|
|
If you nest calls to `Deps.autorun`, then when the outer call stops or
|
|
reruns, the inner call will stop automatically. Subscriptions and
|
|
observers are also automatically stopped when used as part of a
|
|
computation that is rerun, allowing new ones to be established. See
|
|
[`Meteor.subscribe`](#meteor_subscribe) for more information about
|
|
subscriptions and reactivity.
|
|
|
|
If the initial run of an autorun throws an exception, the computation
|
|
is automatically stopped and won't be rerun.
|
|
|
|
{{> api_box deps_flush }}
|
|
|
|
Normally, when you make changes (like writing to the database),
|
|
their impact (like updating the DOM) is delayed until the system is
|
|
idle. This keeps things predictable — you can know that the DOM
|
|
won't go changing out from under your code as it runs. It's also one
|
|
of the things that makes Meteor fast.
|
|
|
|
`Deps.flush` forces all of the pending reactive updates to complete.
|
|
For example, if an event handler changes a Session
|
|
variable that will cause part of the user interface to rerender, the
|
|
handler can call `flush` to perform the rerender immediately and then
|
|
access the resulting DOM.
|
|
|
|
An automatic flush occurs whenever the system is idle which performs
|
|
exactly the same work as `Deps.flush`. The flushing process consists
|
|
of rerunning any invalidated computations. If additional
|
|
invalidations happen while flushing, they are processed as part of the
|
|
same flush until there is no more work to be done. Callbacks
|
|
registered with [`Meteor.afterFlush`](#deps_afterflush) are called
|
|
after processing outstanding invalidations.
|
|
|
|
Any auto-updating DOM elements that are found to not be in the
|
|
document during a flush may be cleaned up by Meteor (meaning that
|
|
Meteor will stop tracking and updating the elements, so that the
|
|
browser's garbage collector can delete them). So, if you manually
|
|
call `flush`, you need to make sure that any auto-updating elements
|
|
that you have created by calling [`Meteor.render`](#meteor_render)
|
|
have already been inserted in the main DOM tree.
|
|
|
|
It is illegal to call `flush` from inside a `flush` or from a running
|
|
computation.
|
|
|
|
{{> api_box deps_nonreactive }}
|
|
|
|
Calls `func()` with `Deps.currentComputation` temporarily set to
|
|
`null`. If `func` accesses reactive data sources, these data sources
|
|
will never cause a rerun of the enclosing computation.
|
|
|
|
{{> api_box deps_active }}
|
|
|
|
This value is useful for data source implementations to determine
|
|
whether they are being accessed reactively or not.
|
|
|
|
{{> api_box deps_currentcomputation }}
|
|
|
|
It's very rare to need to access `currentComputation` directly. The
|
|
current computation is used implicitly by
|
|
[`Deps.active`](#deps_active) (which tests whether there is one),
|
|
[`dependency.depend()`](#dependency_depend) (which registers that it depends on a
|
|
dependency), and [`Deps.onInvalidate`](#deps_oninvalidate) (which
|
|
registers a callback with it).
|
|
|
|
{{> api_box deps_oninvalidate }}
|
|
|
|
See [*`computation`*`.onInvalidate`](#computation_oninvalidate) for more
|
|
details.
|
|
|
|
{{> api_box deps_afterflush }}
|
|
|
|
Functions scheduled by multiple calls to `afterFlush` are guaranteed
|
|
to run in the order that `afterFlush` was called. Functions are
|
|
guaranteed to be called at a time when there are no invalidated
|
|
computations that need rerunning. This means that if an `afterFlush`
|
|
function invalidates a computation, that computation will be rerun
|
|
before any other `afterFlush` functions are called.
|
|
|
|
<h2 id="deps_computation"><span>Deps.Computation</span></h2>
|
|
|
|
A Computation object represents code that is repeatedly rerun in
|
|
response to reactive data changes. Computations don't have return
|
|
values; they just perform actions, such as rerendering a template on
|
|
the screen. Computations are created using [`Deps.autorun`](#deps_autorun).
|
|
Use [`stop`](#computation_stop) to prevent further rerunning of a
|
|
computation.
|
|
|
|
Each time a computation runs, it may access various reactive data
|
|
sources that serve as inputs to the computation, which are called its
|
|
dependencies. At some future time, one of these dependencies may
|
|
trigger the computation to be rerun by invalidating it. When this
|
|
happens, the dependencies are cleared, and the computation is
|
|
scheduled to be rerun at flush time.
|
|
|
|
The *current computation*
|
|
([`Deps.currentComputation`](#deps_currentcomputation)) is the
|
|
computation that is currently being run or rerun (computed), and the
|
|
one that gains a dependency when a reactive data source is accessed.
|
|
Data sources are responsible for tracking these dependencies using
|
|
[`Deps.Dependency`](#deps_dependency) objects.
|
|
|
|
Invalidating a computation sets its `invalidated` property to true
|
|
and immediately calls all of the computation's `onInvalidate`
|
|
callbacks. When a flush occurs, if the computation has been invalidated
|
|
and not stopped, then the computation is rerun by setting the
|
|
`invalidated` property to `false` and calling the original function
|
|
that was passed to `Deps.autorun`. A flush will occur when the current
|
|
code finishes running, or sooner if `Deps.flush` is called.
|
|
|
|
Stopping a computation invalidates it (if it is valid) for the purpose
|
|
of calling callbacks, but ensures that it will never be rerun.
|
|
|
|
Example:
|
|
|
|
// if we're in a computation, then perform some clean-up
|
|
// when the current computation is invalidated (rerun or
|
|
// stopped)
|
|
if (Deps.active) {
|
|
Deps.onInvalidate(function () {
|
|
x.destroy();
|
|
y.finalize();
|
|
});
|
|
}
|
|
|
|
{{> api_box computation_stop}}
|
|
|
|
Stopping a computation is irreversible and guarantees that it will
|
|
never be rerun. You can stop a computation at any time, including
|
|
from the computation's own run function. Stopping a computation that
|
|
is already stopped has no effect.
|
|
|
|
Stopping a computation causes its `onInvalidate` callbacks to run
|
|
immediately if it is not currently invalidated.
|
|
|
|
Nested computations are stopped automatically when their enclosing
|
|
computation is rerun.
|
|
|
|
{{> api_box computation_invalidate }}
|
|
|
|
Invalidating a computation marks it to be rerun at
|
|
[flush time](#deps_flush), at
|
|
which point the computation becomes valid again. It is rare to
|
|
invalidate a computation manually, because reactive data sources
|
|
invalidate their calling computations when they change. Reactive data
|
|
sources in turn perform this invalidation using one or more
|
|
[`Deps.Dependency`](#deps_dependency) objects.
|
|
|
|
Invalidating a computation immediately calls all `onInvalidate`
|
|
callbacks registered on it. Invalidating a computation that is
|
|
currently invalidated or is stopped has no effect. A computation can
|
|
invalidate itself, but if it continues to do so indefinitely, the
|
|
result will be an infinite loop.
|
|
|
|
{{> api_box computation_oninvalidate }}
|
|
|
|
`onInvalidate` registers a one-time callback that either fires
|
|
immediately or as soon as the computation is next invalidated or
|
|
stopped. It is used by reactive data sources to clean up resources or
|
|
break dependencies when a computation is rerun or stopped.
|
|
|
|
To get a callback after a computation has been recomputed, you can
|
|
call [`Deps.afterFlush`](#deps_afterflush) from `onInvalidate`.
|
|
|
|
{{> api_box computation_stopped }}
|
|
|
|
{{> api_box computation_invalidated }}
|
|
|
|
This property is initially false. It is set to true by `stop()` and
|
|
`invalidate()`. It is reset to false when the computation is
|
|
recomputed at flush time.
|
|
|
|
{{> api_box computation_firstrun }}
|
|
|
|
This property is a convenience to support the common pattern where a
|
|
computation has logic specific to the first run.
|
|
|
|
<h2 id="deps_dependency"><span>Deps.Dependency</span></h2>
|
|
|
|
A Dependency represents an atomic unit of reactive data that a
|
|
computation might depend on. Reactive data sources such as Session or
|
|
Minimongo internally create different Dependency objects for different
|
|
pieces of data, each of which may be depended on by multiple
|
|
computations. When the data changes, the computations are
|
|
invalidated.
|
|
|
|
Dependencies don't store data, they just track the set of computations to
|
|
invalidate if something changes. Typically, a data value will be
|
|
accompanied by a Dependency object that tracks the computations that depend
|
|
on it, as in this example:
|
|
|
|
var weather = "sunny";
|
|
var weatherDep = new Deps.Dependency;
|
|
|
|
var getWeather = function () {
|
|
weatherDep.depend()
|
|
return weather;
|
|
};
|
|
|
|
var setWeather = function (w) {
|
|
weather = w;
|
|
// (could add logic here to only call changed()
|
|
// if the new value is different from the old)
|
|
weatherDep.changed();
|
|
};
|
|
|
|
This example implements a weather data source with a simple getter and
|
|
setter. The getter records that the current computation depends on
|
|
the `weatherDep` dependency using `depend()`, while the setter
|
|
signals the dependency to invalidate all dependent computations by
|
|
calling `changed()`.
|
|
|
|
The reason Dependencies do not store data themselves is that it can be
|
|
useful to associate multiple Dependencies with the same piece of data.
|
|
For example, one Dependency might represent the result of a database
|
|
query, while another might represent just the number of documents in
|
|
the result. A Dependency could represent whether the weather is sunny
|
|
or not, or whether the temperature is above freezing.
|
|
[`Session.equals`](#session_equals) is implemented this way for
|
|
efficiency. When you call `Session.equals("weather", "sunny")`, the
|
|
current computation is made to depend on an internal Dependency that
|
|
does not change if the weather goes from, say, "rainy" to "cloudy".
|
|
|
|
Conceptually, the only two things a Dependency can do are gain a
|
|
dependent and change.
|
|
|
|
A Dependency's dependent computations are always valid (they have
|
|
`invalidated === false`). If a dependent is invalidated at any time,
|
|
either by the Dependency itself or some other way, it is immediately
|
|
removed.
|
|
|
|
{{> api_box dependency_changed }}
|
|
|
|
{{> api_box dependency_depend }}
|
|
|
|
`dep.depend()` is used in reactive data source implementations to record
|
|
the fact that `dep` is being accessed from the current computation.
|
|
|
|
{{> api_box dependency_hasdependents }}
|
|
|
|
For reactive data sources that create many internal Dependencies,
|
|
this function is useful to determine whether a particular Dependency is
|
|
still tracking any dependency relationships or if it can be cleaned up
|
|
to save memory.
|
|
|
|
<h2 id="ejson"><span>EJSON</span></h2>
|
|
|
|
EJSON is an extension of JSON to support more types. It supports all JSON-safe
|
|
types, as well as:
|
|
|
|
- **Date** (JavaScript `Date`)
|
|
- **Binary** (JavaScript `Uint8Array` or the
|
|
result of [`EJSON.newBinary`](#ejson_new_binary))
|
|
- **User-defined types** (see [`EJSON.addType`](#ejson_add_type). For example,
|
|
[`Meteor.Collection.ObjectID`](#collection_object_id) is implemented this way.)
|
|
|
|
All EJSON serializations are also valid JSON. For example an object with a date
|
|
and a binary buffer would be serialized in EJSON as:
|
|
|
|
{
|
|
"d": {"$date": 1358205756553},
|
|
"b": {"$binary": "c3VyZS4="}
|
|
}
|
|
|
|
Meteor supports all built-in EJSON data types in publishers, method arguments
|
|
and results, Mongo databases, and [`Session`](#session) variables.
|
|
|
|
{{> api_box ejsonParse}}
|
|
|
|
{{> api_box ejsonStringify}}
|
|
|
|
{{> api_box ejsonFromJSONValue}}
|
|
|
|
{{> api_box ejsonToJSONValue}}
|
|
|
|
{{> api_box ejsonEquals}}
|
|
|
|
{{> api_box ejsonClone}}
|
|
|
|
{{> api_box ejsonNewBinary}}
|
|
|
|
Buffers of binary data are represented by `Uint8Array` instances on JavaScript
|
|
platforms that support them. On implementations of JavaScript that do not
|
|
support `Uint8Array`, binary data buffers are represented by standard arrays
|
|
containing numbers ranging from 0 to 255, and the `$Uint8ArrayPolyfill` key
|
|
set to `true`.
|
|
|
|
{{> api_box ejsonIsBinary}}
|
|
|
|
{{> api_box ejsonAddType}}
|
|
|
|
When you add a type to EJSON, Meteor will be able to use that type in:
|
|
|
|
- publishing objects of your type if you pass them to publish handlers.
|
|
- allowing your type in the return values or arguments to
|
|
[methods](#methods_header).
|
|
- storing your type client-side in Minimongo.
|
|
- allowing your type in [`Session`](#session) variables.
|
|
|
|
{{#note}}
|
|
|
|
MongoDB cannot store most user-defined types natively on the server. Your
|
|
type will work in Minimongo, and you can send it to the client using a custom
|
|
publisher, but MongoDB can only store the types defined in
|
|
[BSON](http://bsonspec.org/).
|
|
|
|
{{/note}}
|
|
|
|
Instances of your type should implement the following interface:
|
|
|
|
{{> api_box ejsonTypeClone}}
|
|
|
|
{{> api_box ejsonTypeEquals}}
|
|
|
|
The `equals` method should define an [equivalence
|
|
relation](http://en.wikipedia.org/wiki/Equivalence_relation). It should have
|
|
the following properties:
|
|
|
|
- *Reflexivity* - for any instance `a`: `a.equals(a)` must be true.
|
|
- *Symmetry* - for any two instances `a` and `b`: `a.equals(b)` if and only if `b.equals(a)`.
|
|
- *Transitivity* - for any three instances `a`, `b`, and `c`: `a.equals(b)` and `b.equals(c)` implies `a.equals(c)`.
|
|
|
|
{{> api_box ejsonTypeName}}
|
|
{{> api_box ejsonTypeToJSONValue}}
|
|
|
|
For example, the `toJSONValue` method for
|
|
[`Meteor.Collection.ObjectID`](#collection_object_id) could be:
|
|
|
|
function () {
|
|
return this.toHexString();
|
|
};
|
|
|
|
<h2 id="meteor_http"><span>Meteor.http</span></h2>
|
|
|
|
`Meteor.http` provides an HTTP API on the client and server. To use
|
|
these functions, add the HTTP package to your project with `$ meteor add
|
|
http`.
|
|
|
|
{{> api_box httpcall}}
|
|
|
|
This function initiates an HTTP request to a remote server. It returns
|
|
a result object with the contents of the HTTP response. The result
|
|
object is detailed below.
|
|
|
|
On the server, this function can be run either synchronously or
|
|
asynchronously. If the callback is omitted, it runs synchronously,
|
|
and the results are returned once the request completes. This is
|
|
useful when making server-to-server HTTP API calls from within Meteor
|
|
methods, as the method can succeed or fail based on the results of the
|
|
synchronous HTTP call. In this case, consider using
|
|
[`this.unblock()`](#method_unblock) to allow other methods to run in
|
|
the mean time. On the client, this function must be used
|
|
asynchronously by passing a callback.
|
|
|
|
Both HTTP and HTTPS protocols are supported. The `url` argument must be
|
|
an absolute URL including protocol and host name on the server, but may be
|
|
relative to the current host on the client. The `query` option
|
|
replaces the query string of `url`. Parameters specified in `params`
|
|
that are put in the URL are appended to any query string.
|
|
For example, with a `url` of `"/path?query"` and
|
|
`params` of `{foo:"bar"}`, the final URL will be `"/path?query&foo=bar"`.
|
|
|
|
The `params` are put in the URL or the request body, depending on the
|
|
type of request. In the case of request with no bodies, like GET and
|
|
HEAD, the parameters will always go in the URL. For a POST or other
|
|
type of request, the parameters will be encoded into the body with a
|
|
standard `x-www-form-urlencoded` content type, unless the `content`
|
|
or `data` option is used to specify a body, in which case the
|
|
parameters will be appended to the URL instead.
|
|
|
|
The callback receives two arguments, `error` and `result`. The
|
|
`error` argument will contain an Error if the request fails in any
|
|
way, including a network error, time-out, or an HTTP status code in
|
|
the 400 or 500 range. In case of a 4xx/5xx HTTP status code, the
|
|
`response` property on `error` matches the contents of the result
|
|
object. When run in synchronous mode, either `result` is returned
|
|
from the function, or `error` is thrown.
|
|
|
|
Contents of the result object:
|
|
|
|
<dl class="objdesc">
|
|
|
|
<dt><span class="name">statusCode</span>
|
|
<span class="type">Number</span></dt>
|
|
<dd>Numeric HTTP result status code, or <code>null</code> on error.</dd>
|
|
|
|
<dt><span class="name">content</span>
|
|
<span class="type">String</span></dt>
|
|
<dd>The body of the HTTP response as a string.</dd>
|
|
|
|
<dt><span class="name">data</span>
|
|
<span class="type">Object or <code>null</code></span></dt>
|
|
<dd>If the response headers indicate JSON content, this contains the body of the document parsed as a JSON object.</dd>
|
|
|
|
<dt><span class="name">headers</span>
|
|
<span class="type">Object</span></dt>
|
|
<dd>A dictionary of HTTP headers from the response.</dd>
|
|
|
|
</dl>
|
|
|
|
Example server method:
|
|
|
|
Meteor.methods({checkTwitter: function (userId) {
|
|
check(userId, String);
|
|
this.unblock();
|
|
var result = Meteor.http.call("GET", "http://api.twitter.com/xyz",
|
|
{params: {user: userId}});
|
|
if (result.statusCode === 200)
|
|
return true
|
|
return false;
|
|
}});
|
|
|
|
Example asynchronous HTTP call:
|
|
|
|
Meteor.http.call("POST", "http://api.twitter.com/xyz",
|
|
{data: {some: "json", stuff: 1}},
|
|
function (error, result) {
|
|
if (result.statusCode === 200) {
|
|
Session.set("twizzled", true);
|
|
}
|
|
});
|
|
|
|
|
|
{{> api_box http_get}}
|
|
{{> api_box http_post}}
|
|
{{> api_box http_put}}
|
|
{{> api_box http_del}}
|
|
|
|
|
|
<h2 id="email"><span>Email</span></h2>
|
|
|
|
The `email` package allows sending email from a Meteor app. To use it, add the
|
|
package to your project with `$ meteor add email`.
|
|
|
|
The server reads from the `MAIL_URL` environment variable to determine how to
|
|
send mail. Currently, Meteor supports sending mail over SMTP; the `MAIL_URL`
|
|
environment variable should be of the form
|
|
`smtp://USERNAME:PASSWORD@HOST:PORT/`. For apps deployed with `meteor deploy`,
|
|
`MAIL_URL` defaults to an account (provided by
|
|
[Mailgun](http://www.mailgun.com/)) which allows apps to send up to 200 emails
|
|
per day; you may override this default by assigning to `process.env.MAIL_URL`
|
|
before your first call to `Email.send`.
|
|
|
|
If `MAIL_URL` is not set (eg, when running your application locally),
|
|
`Email.send` outputs the message to standard output instead.
|
|
|
|
{{> api_box email_send }}
|
|
|
|
You must provide the `from` option and at least one of `to`, `cc`, and `bcc`;
|
|
all other options are optional.
|
|
|
|
`Email.send` only works on the server. Here is an example of how a
|
|
client could use a server method call to send an email. (In an actual
|
|
application, you'd need to be careful to limit the emails that a
|
|
client could send, to prevent your server from being used as a relay
|
|
by spammers.)
|
|
|
|
// In your server code: define a method that the client can call
|
|
Meteor.methods({
|
|
sendEmail: function (to, from, subject, text) {
|
|
check([to, from, subject, text], [String]);
|
|
|
|
// Let other method calls from the same client start running,
|
|
// without waiting for the email sending to complete.
|
|
this.unblock();
|
|
|
|
Email.send({
|
|
to: to,
|
|
from: from,
|
|
subject: subject,
|
|
text: text
|
|
});
|
|
}
|
|
});
|
|
|
|
// In your client code: asynchronously send an email
|
|
Meteor.call('sendEmail',
|
|
'alice@example.com',
|
|
'bob@example.com',
|
|
'Hello from Meteor!',
|
|
'This is a test of Email.send.');
|
|
|
|
{{/better_markdown}}
|
|
|
|
<h2 id="assets"><span>Assets</span></h2>
|
|
|
|
{{#better_markdown}}
|
|
`Assets` allows server code in a Meteor application to access static server
|
|
assets, which are located in the `private` subdirectory of an application's
|
|
tree.
|
|
|
|
{{> api_box assets_getText }}
|
|
{{> api_box assets_getBinary }}
|
|
|
|
Static server assets are included by placing them in the application's `private`
|
|
subdirectory. For example, if an application's `private` subdirectory includes a
|
|
directory called `nested` with a file called `data.txt` inside it, then server
|
|
code can read `data.txt` by running:
|
|
|
|
var data = Assets.getText('nested/data.txt');
|
|
{{/better_markdown}}
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<template name="api_box">
|
|
<div class="api {{bare}}">
|
|
<h3 id="{{id}}">
|
|
<a class="name selflink" href="#{{id}}">{{{name}}}</a>
|
|
{{#if locus}}
|
|
<span class="locus">{{locus}}</span>
|
|
{{/if}}
|
|
</h3>
|
|
|
|
<div class="desc">
|
|
{{#each descr}}{{#better_markdown}}{{{this}}}{{/better_markdown}}{{/each}}
|
|
</div>
|
|
|
|
{{#if args}}
|
|
<h4>Arguments</h4>
|
|
{{> api_box_args args}}
|
|
{{/if}}
|
|
|
|
{{#if options}}
|
|
<h4>Options</h4>
|
|
{{> api_box_args options}}
|
|
{{/if}}
|
|
|
|
{{#if body}}
|
|
{{#better_markdown}}{{{body}}}{{/better_markdown}}
|
|
{{/if}}
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<template name="api_box_args">
|
|
<dl class="args">
|
|
{{#each this}}
|
|
<dt><span class="name">{{{name}}}</span>
|
|
<span class="type">
|
|
{{#if type_link}}
|
|
<a href="#{{type_link}}">{{{type}}}</a>
|
|
{{else}}
|
|
{{{type}}}
|
|
{{/if}}
|
|
</span></dt>
|
|
<dd>{{#better_markdown}}{{{descr}}}{{/better_markdown}}</dd>
|
|
{{/each}}
|
|
</dl>
|
|
</template>
|
|
|
|
|
|
<template name="api_section_helper">
|
|
<h2 id="{{id}}"><a href="#{{id}}" class="selflink"><span>{{name}}</span></a></h2>
|
|
</template>
|