Devshop September
Meteor Göteborg
Agenda
- Install Meteor (0.9.2)
Install Meteorite- Introduction
- Setup
- Iron Router + Templates + Forms
- Publications
- Subscriptions
- Theming
Install latest Meteor
curl https://install.meteor.com/ | sh
Update to Meteor 0.9.2
meteor update
Introduction
- We will build a race timer app with timers per each participants per race
- Start by bootstrapping with the github repository
- Try to solve each problem before we show the solution, each step (except step1) contains our solutions.
- Learn about Pub/Sub and Iron Router
studiointeract/meteor-multi-timer
Setup
- Clone the sample application
- Start the application
git clone git@github.com:studiointeract/meteor-multi-timer.git
cd meteor-multi-timer
git checkout step1
meteor
#step1
https://slides.com/timbrandin/devshop-september
Iron Router
- Stop the application
- Add iron:router from Atmosphere (new)
- Start the application again
CTRL + C
meteor add iron:router
meteor
#step2
Home route
- Create a home route
- Create a home template listing races
Router.map(function (){
this.route('home', {
path: '/'
});
});
<template name="home">
<ul>
{{#each races}}
<li>
<a href="/race/{{_id}}">{{name}}</a>
</li>
{{/each}}
</ul>
</template>
client/routes.js
client/views/home/home.html
#step2
Adding races
- Add a form to input new races to home
- Create a submit handler that adds the race
...
</ul>
<form>
<input type="text" placeholder="Add a race">
<button type="submit">Add</button>
</form>
</template>
Template.home.events({
'submit form': function(event, template) {
event.preventDefault();
var name = template.find('input').value;
template.find('input').value = '';
Races.insert({name: name});
}
});
client/views/home/home.js
client/views/home/home.html
#step2
Race route
- Create a race route
- Create a race template listing participants
...
this.route('race', {
path: '/race/:_id'
});
});
<template name="race">
<ul>
{{#each participants}}
<li>
{{name}}
</li>
{{/each}}
</ul>
</template>
client/views/race/race.js
client/routes.js
#step2
Adding participants
- Add a form to input new participants
- Create a submit handler that add a person
...
</ul>
<form>
<input type="text" placeholder="Add a participant">
<button type="submit">Add</button>
</form>
</template>
Template.race.events({
'submit form': function(event, template) {
event.preventDefault();
var name = template.find('input').value;
template.find('input').value = '';
var _race = Routes.current().params._id;
Participants.insert({name: name, _race: _race});
}
});
client/views/race/race.js
client/views/race/race.html
#step2
Add collection data to the templates
- Fetch data from the Races collection
- Fetch data from the Participants collection
...
this.route('home', {
path: '/',
data: function() {
return {
races: Races.find()
}
}
});
...
...
this.route('race', {
path: '/race/:_id',
data: function() {
return {
participants: Participants.find({_race: this.params._id})
}
}
});
...
client/routes.js
client/routes.js
Step2
Checkout step2 options
- Stash your changes and checkout
- Commit your changes to your own branch
git stash
git checkout step2
git checkout -b my-step1
git commit -am "My changes to step1"
git checkout step2
Publications
- Remove the autopublish package
- Start the application again
- No data should be visible in the browser
meteor remove autopublish
meteor
Setup publications
- Create a races publication on the server
- And one for a single race, also returning participants
...
if (Meteor.isServer) {
Meteor.publish('races', function() {
return Races.find();
});
}
...
Meteor.publish('race', function(_race) {
var race = Races.find({_id: _race});
var participants = Participants.find({_race: _id});
return [race, participants];
});
...
collections/participants.js
collections/races.js
#step3
Setup subscriptions
- Add a subscription for races to the home route.
- And one for a single race on the race route.
...
this.route('home', {
path: '/',
waitOn: function() {
return Meteor.subscribe('races');
},
...
...
this.route('race', {
path: '/race/:_id',
waitOn: function() {
return Meteor.subscribe('race', this.params._id);
},
...
client/routes.js
#step3
client/routes.js
Step3
Checkout step3 options
- Stash your changes and checkout
- Commit your changes to your own branch
git stash
git checkout step3
git checkout -b my-step2
git commit -am "My changes to step2"
git checkout step3
Timing
- Create helpers for timer formatting, a session variable and click to start/stop.
- Show the timer in the template
Template.race.events({
...
'click li': function() {
if (!this.timestamp) {
Participants.update({_id: this._id}, {$set: {timestamp: (+new Date)}});
}
else if (this.end) {
Participants.update({_id: this._id}, {
$set: {
timestamp: (+new Date),
},
$unset: {
end: true
}
});
}
else {
Participants.update({_id: this._id}, {$set: {end: (+new Date)}});
}
}
});
Template.race.helpers({
timer: function() {
var time = Math.max(0, Session.get('now') - this.timestamp);
return moment.utc(time).format("mm:ss.S");
},
finish: function() {
var time = Math.max(0, this.end - this.timestamp);
return moment.utc(time).format("mm:ss.S");
}
});
Meteor.setInterval(function() {
Session.set('now', (+new Date));
}, 100);
...
<li>
<span class="timer">
{{#if end}}
{{finish}}
{{else}}
{{timer}}
{{/if}}
</span>
{{name}}
</li>
...
client/views/race/race.html
#step4
client/views/race/race.js
Step4
Checkout step4 options
- Stash your changes and checkout
- Commit your changes to your own branch
git stash
git checkout step4
git checkout -b my-step3
git commit -am "My changes to step3"
git checkout step4
Devshop September 2014
By Tim Brandin
Devshop September 2014
- 2,428