In the 9th step (Adding user accounts) of official tutorial "simple-todos" of Meteor 1.0, if you start server while leaving some old data (todo items) created in previous steps, you will find that there's no username before the todo text.
But if you clear all old data (click remove button on web page, or use meteor reset
),
and create new todo items with a signed in username, you will find the username appear.
Data binding between Template and Collection
The following modified version simple-todos works:
simple-todos.html:
<head>
<title>Todo List</title>
</head>
<body>
<div class="container">
<header>
<h1>Todo List</h1>
<label class="hide-completed">
<input type="checkbox" checked="{{hideCompleted}}" />
Hide Completed Tasks
</label>
{{> loginButtons}}
{{#if currentUser}}
<form class="new-task">
<input type="text" name="text" placeholder="Type to add tasks" />
</form>
{{/if}}
</header>
<ul>
{{#each todoitems}}
{{> todo}}
{{/each}}
</ul>
</div>
</body>
<template name="todo">
<li class="{{#if checked}}checked{{/if}}">
<button class="delete">×</button>
<input type="checkbox" checked="{{checked}}" class="toggle-checked" />
<span class="text"><strong>{{username}}</strong> - {{text}} at {{creDate}}</span>
</li>
</template>
simple-todos.js:
Tasks = new Mongo.Collection("tododb");
if (Meteor.isClient) {
Template.body.helpers({
todoitems: function () {
if (Session.get("hideCompleted")) {
return Tasks.find({checked: {$ne: true}}, {sort: {createdAt: -1}});
} else {
return Tasks.find({}, {sort: {createdAt: -1}});
}
},
hideCompleted: function () {
return Session.get("hideCompleted");
}
});
Template.body.events({
"submit .new-task": function (event) {
var text = event.target.text.value;
Tasks.insert({
text: text,
createdAt : new Date(),
owner: Meteor.userId(),
username: Meteor.user().username
});
event.target.text.value = "";
return false;
},
"change .hide-completed input": function (event) {
Session.set("hideCompleted", event.target.checked);
}
});
Template.todo.helpers({
creDate: function () {
return this.createdAt;
}
});
Template.todo.events({
"click .toggle-checked": function () {
Tasks.update(this._id, {$set: {checked: ! this.checked}});
},
"click .delete": function () {
Tasks.remove(this._id);
}
});
Accounts.ui.config({
passwordSignupFields: "USERNAME_ONLY"
});
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
So we can conclude (the left hand side of "<=>" is template in html file, while js codes on the right hand side):
-
The name after #each is a helper function which defined in js file, and returns a subset of a collection:
{{#each todoitems}} <=> Template.body.helpers -> todoitems: function () {...};
-
Variables in {{...}} in a template is the attributes of the object in collection, represented by the template:
<strong>{{username}}</strong> - {{text}} <=> Tasks.insert({ text: text, ..., username: Meteor.user().username });
or a helper function ({{creDate}} here).
- "this" in helper function refers to the template the function based on.