On Github stevekane / component-talk
Javascript developer living in Bucktown and currently working for Mantra, Inc building MVPs for new startups.
//handlebars template
{{secondsViewed}}
//javascript code
App.OurTimetrackerComponent = Ember.Component.extend({
msViewed: 0,
oldTime: null,
newTime: null,
secondsViewed: function () {
var msViewed = this.get('msViewed');
return Math.round(msViewed);
},
startTimer: function () {
Ember.run.later(this, function () {
var newTime = Date.now()
, oldTime = this.get('oldTime') || Date.now()
, detaMs = newTime - oldTime;
this.incrementProperty('msViewed', deltaMs);
this.set('oldtime', newtime);
}, 500);
}.on('didInsertElement')
});
{{! display the time a user has spent on this view }}
{{our-timetracker}}
{{our-timetracker action="logTimeStamp"}}
//snippet from our origin timetracker
startTimer: function () {
Ember.run.later(this, function () {
var newTime = Date.now()
, oldTime = this.get('oldTime') || Date.now()
, deltaMs = newTime - oldTime;
this.incrementProperty('msViewed', deltaMs);
//new
this.sendAction("action", this.get('msViewed'));
//endnew
this.set('oldTime', newTime);
}, 500);
}.on('didInsertElement')
{{our-timetracker action="logTimeStamp"}}
App.SomeController = Ember.Controller.extend({
actions: {
logTimeStamp: function (ms) {
var lsTimeStamps=localStorage['timestamps'] || "[]"
, timeStamps=JSON.parse(lsTimeStamps)
, stringifiedTimeStamps;
timeStamps.push(ms);
stringifiedTimeStamps=JSON.stringify(timeStamps);
localStorage['timestamps']=stringifiedTimeStamps);
}
}
});
App.SomeController = Ember.Controller.extend({
actions: {
logTimeStamp: function (ms) {
this.websocket.send(ms);
}
}
});
App.TimeGraphComponent = Ember.Component.extend({
actions: {
logTimeStamp: function (ms) {
//weird d3 code belongs here
}
}
});
@heyjinkim's blogpost w/ real implementation
{{! some.handlebars }}
{{! template for somecontroller and someview }}
{{our-timetracker action="logTimeStamp" msViewed=view.msOnPage}}
{{our-timegraph data=view.msOnPage}}
App.SomeView = Ember.View.extend({
msOnPage: 0
});
{{our-timetracker action="logTimeStamp" msViewed=view.msOnPage}}
changes to bound properties are propagated to every part of your app that depends on them...for free.
{{our-timetracker outputBus=timeBus}}
{{our-timegraph inputBus=timeBus}}
App.SomeController = Ember.Controller.extend({
//not an ember builtin!
timeBus: App.Bus.create()
});
App.TimetrackerComponent = Ember.Component.extend({
//psuedocode for brevity
onTick (ms): function () {
var outputBus = this.get('outputBus');
outputBus.push({
timeStamp: ms,
otherData: //something
});
}
});
App.TimegraphComponent = Ember.Component.extend({
didInsertElement: function () {
var inputBus = this.get('inputBus');
inputBus.on('data', function (data) {
this.graph(data.timeStamp);
});
}
});
//data is a blob of weather data fetched by the Route
App.WeatherController = Ember.Controller.extend({
cityName: "Chicago",
activeDateTime: Date.now(),
activeDaysData: function () {
var activeDateTime = this.get('activeDateTime')
, data = this.get('data');
this.get('data').filterProperty('date', activeDateTime);
}.property('activeDateTime', 'data'),
isMetric: true,
}
});
Computes current temperature
Displays City Name, Current Date and Time, Summary
{{weather-overview
cityName=cityName
dateTime=activeDateTime
data=activeDaysData}}
Computes and displays average windspeed, humidity, precipitation
{{weather-daily-averages data=activeDaysData isMetric=isMetric}}
Computes current temperature and activeDays overview
Displays temperature, and graphic based on overview
Toggles "isMetric" value via clicks
{{weather-graphical-overview
data=activeDaysData
dateTime=activeDateTime
isMetric=isMetric}}
Has an internal state to track what is being displayed
Contains "controls" component and "graph component"
{{weather-graph-wrapper data=activeDaysData isMetric=isMetric}}
Computes/displays range of a type of data
State change will cause graph to render new Data
{{weather-graph data=activeDaysData state=state isMetric=isMetric}}
We could further enhance this component by passing in
a range of hours, a scale, or even display properties
Changes "state" based on clickable buttons
NOTE: this is really just a set of "tabs" and could be further generalized
{{weather-graph-controls state=state}}
Graph component may be used elsewhere and have its state driven by other means
Controls component may be used to drive some other state, perhaps tabs?
Create a "daily overview" component
Create a "weekly overview list" component that USES the "daily overview" component in its template
{{! weather-weekly-overview template }}
{{#each day in days}}
{{weather-daily-overview data=day.data}}
{{/each}}
Clicking a "daily overview" will affect the activeDateTime
Daily overview component may be used elsewhere
Weekly overview is concerned with determining list of daily data
Daily overview is concerned with computing/displaying daily data
Let's group the first three components into "overview wrapper" component as we have done in with the previous arrangements
{{! weather.handlebars }}
{{weather-overview-wrapper
cityName=cityName
dateTime=activeDateTime
data=activeDaysData
isMetric=isMetric}}
{{weather-graph-wrapper
data=activeDaysData
isMetric=isMetric}}
{{weather-weekly-overview
data=data
dateTime=activeDateTime
isMetric=isMetric}}