All notes
Meteorjs

Basics

Start with React

guide.meteor.com: react.


# To install meteorjs:
curl https://install.meteor.com/ | sh

meteor create simple-todos
cd simple-todos
meteor # Run the app.
# -p, --port
meteor -p 3000

meteor npm install --save react react-dom

Commands

debug

The server process will be suspended just before the first statement of server code that would normally execute.

In order to continue execution of server code, use either the web-based Node Inspector or the command-line debugger.

Breakpoints can be set using the debugger keyword, or through the web UI of Node Inspector (“Sources” tab).

The server process debugger will listen for incoming connections from debugging clients, such as node-inspector, on port 5858 by default. To specify a different port use the --debug-port option.

Attach client

nodejs.org: inspector.

For Chrome DevTools 55+:

Option 1: Open "chrome://inspect" in a Chromium-based browser. Click the Configure button and ensure your target host and port are listed. Then select your Node.js app from the list.
Option 2: Install the Chrome Extension NIM (Node Inspector Manager).

Debugger did not attach after 5 minutes; continuing

github.com.

try meteor --inspect or meteor --inspect-brk.

mongo


meteor mongo

# This opens a console into your app's local development database. Into the prompt, type:
# db.tasks.insert({ text: "Hello world!", createdAt: new Date() });

npm

docs.meteor.com.


meteor npm install lodash --save

Why use "meteor npm" instead of just "npm"

shell

When meteor shell is executed in an application directory where a server is already running, it connects to the server and starts an interactive shell for evaluating server-side code.

Import modules



import { CT } from './imports/ct';
CT.findOne(someId); // Success!

Blaze

Templates

Template tags

Double braced template tags

Double-braced template tags, e.g. {{pageTitle}}. When they are within block template tags, most likely they refer to properties of the current item. Or they could refer to template helpers.



{{frob a b c verily=true}}
// calls:
frob(a, b, c, Spacebars.kw({verily: true}))

Inclusion template tags

Inclusion template tags {{> templateName}. Everything inside "template" tags is compiled into Meteor templates, which can be included inside HTML with {{> templateName}} or referenced in your JavaScript with Template.templateName.

Block template tags

Block template tags, e.g. {{#each}}, {{#each}} and {{#if}}. They let you add logic and data to your views.

Also, the body section can be referenced in your JavaScript with Template.body.

Triple-braced template tags

{{{content}}} - Triple-braced template tags are used to insert raw HTML.

imports/ui/body.html:



<body>
  <div class="container">
    <header>
      <h1>Todo List</h1>
      <form class="new-task">
        <input type="text" name="text" placeholder="Type to add new tasks" />
      </form>
    </header>
 
    <ul>
      {{#each tasks}}
        {{> task}}
      {{/each}}
    </ul>
  </div>
</body>
 
<template name="task">
  <li>{{text}}</li>
</template>


////////// imports/ui/body.js:

import { Template } from 'meteor/templating';

import { Tasks } from '../api/tasks.js';
 
import './body.html';

//----- We can pass data into templates from JavaScript code by defining "helpers".
 
Template.body.helpers({
// Method 1: use array.
//  tasks: [
//    { text: 'This is task 1' },
//    { text: 'This is task 2' },
//    { text: 'This is task 3' },
//  ],

// Method 2: use MongoDB:
  tasks() {
    // Show newest tasks at the top
    return Tasks.find({}, { sort: { createdAt: -1 } });
  },
});

Template.body.events({
  'submit .new-task'(event) {
    // Prevent default browser form submit
    event.preventDefault();
 
    // Get value from form element
    const target = event.target;
    const text = target.text.value;
 
    // Insert a task into the collection
    Tasks.insert({
      text,
      createdAt: new Date(), // current time
    });
 
    // Clear form
    target.text.value = '';
  },
});

////////// imports/api/tasks.js

import { Mongo } from 'meteor/mongo';
 
export const Tasks = new Mongo.Collection('tasks');

////////// server/main.js

import '../imports/api/tasks.js';

////////// client/main.js

import '../imports/ui/body.js';

Template helpers

Server-side calculation

ibm.com



//---------- Template
<template name="analytics">
  {{#with analyticResult}}
    ... Do something ...
  {{/with}}
</template>

//---------- server/main.js
Meteor.methods({ 
  serverSideComputation: function() {
    var result = {};
    result.foo = "Hello ";
    result.bar = "World!";
    return result;
  },
});

//---------- Using the Session
Template.analytics.helpers({
  analyticResult: function() {
    if (Session.get('someIdentifier') === undefined) {
      Meteor.call('serverSideComputation', function(err, data) {
        Session.set('someIdentifier', data);
      });
    }
    return Session.get('someIdentifier);
  }
});

//---------- Using a Reactive Variable
Template.analytics.created = function() {
  this.someIdentifier = new ReactiveVar(false);
}
Template.analytics.helpers({
  analyticResult: function() {
    if (Template.instance().someIdentifier.get()) === false) {
      Meteor.call('serverSideComputation', function(err, data) {
        Template.instance().someIdentifier.set(data.foo+data.bar);
      });
    }
    return Template.instance().someIdentifier.get();
  }
});

Mongo

Collections

docs.meteor.com: collections.



// Common code on client and server declares a DDP-managed Mongo collection.
const Chatrooms = new Mongo.Collection('chatrooms');
const Messages = new Mongo.Collection('messages');

// Return an array of my messages.
const myMessages = Messages.find({ userId: Meteor.userId() }).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:

* On the server, a collection with that name is created on a backend Mongo server.
* On the client, a Minimongo instance is created. Minimongo is essentially an in-memory, non-persistent implementation of Mongo in pure JavaScript.
* When you write to the database on the client (insert, update, remove), the command is executed locally immediately, and, simultaneously, it’s sent to the server and executed there too. This happens via stubs, because writes are implemented as methods.

find, findOne

"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. Cursors also implement ES2015’s iteration protocols.

Cursors are a reactive data source.

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.

"findOne" finds the first document that matches the selector, as ordered by "sort" and "skip" options. Returns undefined if no matching document is found.

Equivalent to find(selector, options).fetch()[0] with options.limit = 1.

Cursors

forEach



// Print the titles of the five top-scoring posts.
const topPosts = Posts.find({}, { sort: { score: -1 }, limit: 5 });
let count = 0;
topPosts.forEach((post) => {
  console.log(`Title of post ${count}: ${post.title}`);
  count += 1;
});

ReactiveVar

docs.meteor.com: reactive-var.