Created
August 10, 2012 15:02
-
-
Save lancejpollard/3314813 to your computer and use it in GitHub Desktop.
Tower + Ember Views
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Random helper method to force Ember to render (I think this is it, comes in handy) | |
Ember.fast = -> | |
Ember.run.autorun() | |
Ember.run.currentRunLoop.flush('render') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/client/views/users/new.coffee | |
App.UserNewView = Ember.View.extend(templateName: 'new') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# config/routes.coffee | |
Tower.Route.draw -> | |
@resources 'users' | |
@resources 'posts' | |
# The `resources` method creates 7 routes mapping to 7 controller actions. | |
# It creates those routes with the `match` method. | |
# The `match` method on the client is overridden to include this: | |
# `Tower.router.insertRoute(route)` | |
# That then builds the state tree on the router here: | |
# https://github.com/viatropos/tower/blob/402f19595f0d2fe1f85c973fead7d76fd682e820/packages/tower-net/client/states.coffee#L68 | |
# Then see the `Ember.Route.create` in states.coffee. | |
# It delegates `enter`, `exit`, and `connectOutlets` to the controller. | |
# The controller calls `enter` when it first enters, | |
# and `enterAction` when it switches between actions. Same with exit/exitAction. | |
# The `route.connectOutlets` calls `controller.call`, which actually calls | |
# the action on the controller (and runs the before/after callbacks like normal). | |
# The last part is calling `@render 'someAction'` from controller action method, | |
# which gets expanded into the `viewClass` and figures out the outlet to render this | |
# action view into. That's the part I'm finishing now. | |
# Currently it's hacked in partly here: | |
# https://github.com/viatropos/tower/blob/402f19595f0d2fe1f85c973fead7d76fd682e820/packages/tower-view/shared/rendering.coffee#L15 | |
# and here: | |
# https://github.com/viatropos/tower/blob/402f19595f0d2fe1f85c973fead7d76fd682e820/packages/tower-view/client/emberHelper.coffee#L22 | |
# The other last part is the Watchfile task that builds the templates.js | |
# | |
# From the developers perspective, for a resource like "users", | |
# all you do is write templates, single-line routes, | |
# and a controller with the actions that call `@render action`. | |
# You can pass in an `@render 'show', outlet: 'popup'` too, but the simple case is 1 outlet. | |
# All of this will be implemented as defaults so you don't have to write any actions on the controller. | |
# | |
# Then in the templates, you'd have an {{action "destroy"}} do destroy a record, | |
# but this hasn't been implemented yet. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/client/views/users/show.coffee | |
App.UserShowView = Ember.View.extend(templateName: 'show') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# See the Watchfile method below, which generates the templates.js that basically looks like this: | |
Ember.TEMPLATES['new'] = Ember.computed(-> Ember.Handlebars.compile('new user!')) | |
Ember.TEMPLATES['show'] = Ember.computed(-> Ember.Handlebars.compile('show user!')) | |
# The ideal/optimized way of compiling the ember templates is not fully fleshed out yet, but using computed properties like this basically lazily compiles them, which is good enough for now. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// this is what's actually generated, the templates.coffee is for human readability :) | |
// will clean this up over time | |
Tower.View.cache = { | |
'app/views/users/show': Ember.computed(function() { return Ember.Handlebars.compile('show!'); }) | |
}; | |
_.extend(Ember.TEMPLATES, Tower.View.cache); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class App.UsersController extends Tower.Controller | |
new: -> | |
@render 'new' | |
show: -> | |
@render 'show' # Ember.TEMPLATES['app/views/users/show'] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
coffeecup = require('coffeecup') | |
watch /app\/views.*\.coffee$/ | |
update: (path, callback) -> | |
try | |
nodes = path.replace("app/views/", "").split("/") | |
name = {} | |
data = File.read(path) | |
id = nodes.join("/") | |
selector = id | |
name = "" | |
#@broadcast body: data, id: id, selector: selector, path: "/#{name}" | |
files = File.files("app/views") | |
result = [] | |
for file in files | |
continue unless file.match(/app\/views\/admin\/(index|tiles.*|categories.*).coffee$/) | |
continue unless file.match(/\.coffee$/) | |
result.push [file.replace(/\.coffee$/, ""), File.read(file)] | |
template = "Tower.View.cache =\n" | |
# this is different from before | |
iterator = (item, next) => | |
template += " '#{item[0]}': Ember.Handlebars.compile('" | |
# make it render to HTML for ember | |
template += "#{coffeecup.render(item[1])}')\n" | |
next() | |
async.forEachSeries result, iterator, (error) => | |
template += '_.extend(Ember.TEMPLATES, Tower.View.cache)\n' | |
mint.coffee template, bare: true, (error, string) => | |
if error | |
console.log error | |
return callback(error) | |
else | |
File.write "public/javascripts/templates.js", string | |
callback() | |
catch error | |
callback(error) | |
client: | |
update: (data) -> | |
Tower.View.cache ||= {} | |
Tower.View.cache[data.id] = Ember.TEMPLATES[data.id] = data | |
### | |
if data.reload | |
window.location = data.path | |
else | |
Tower.get data.path | |
### |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I wonder what would be the relation between controller and router. In ember -- these are conceptually different things. Here in tower you seems to "merge" controller and router in a more traditional MVC approach. Is that correct observation or you still plan to introduce a separate routing concept? (as I understand, Tower.router is wrapper around ember router, and supposed to be used only internally -- or it can be extended, e.g. by handling "enter" event in a custom way?).