Skip to content

Instantly share code, notes, and snippets.

@ile
Created October 27, 2013 21:53
Show Gist options
  • Save ile/7188310 to your computer and use it in GitHub Desktop.
Save ile/7188310 to your computer and use it in GitHub Desktop.
Racer bug #164, code to reproduce. https://github.com/codeparty/racer/issues/164
<import: src="./home">
<import: src="./list">
<import: src="./things">
<!--
Derby templates are similar to Handlebars, except that they are first
parsed as HTML, and there are a few extensions to make them work directly
with models. A single HTML template defines the HTML output, the event
handlers that update the model after user interaction, and the event handlers
that update the DOM when the model changes.
As in Handlebars, double curly braces output a value literally. Derby
templates add single curly braces, which output a value and set up
model <- -> view bindings for that object.
Elements that end in colon define template names. Pre-defined templates
are capitalized by convention, but template names are case-insensitive.
Pre-defined templates are automatically included when the page is rendered.
-->
<Header:>
<body class="{{dash($ns)}}">
<ui:connectionAlert>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="/">Project</a>
<div class="nav-collapse">
<ul class="nav">
<!-- Other templates are included like HTML elements -->
<app:navLink title="Home" href="/">
<app:navLink title="List" href="/list">
<app:navLink title="Things" href="/things">
</ul>
</div>
</div>
</div>
</div>
<div class="content">
<div class="container">
<Footer:>
</div>
</div>
<footer>
<div class="container">
<p>&copy; Company 2012</p>
</div>
</footer>
<navLink:>
<li class="{{#if equal($url, @href)}}active{{/}}">
<a href="{{@href}}">{{@title}}</a>
</li>
var app = require('derby').createApp(module)
.use(require('derby-ui-boot'))
.use(require('../../ui'))
// ROUTES //
// Derby routes are rendered on the client and the server
app.get('/', function(page) {
page.render('home');
});
app.get('/list', function(page, model, params, next) {
// This value is set on the server in the `createUserId` middleware
var userId = model.get('_session.userId');
// Create a scoped model, which sets the base path for all model methods
var user = model.at('users.' + userId);
// Create a mongo query that gets the current user's items
var itemsQuery = model.query('items', {userId: userId});
// Get the inital data and subscribe to any updates
model.subscribe(user, itemsQuery, function(err) {
if (err) return next(err);
// Create references that can be used in templates or controller methods
model.ref('_page.user', user);
itemsQuery.ref('_page.items');
console.log(itemsQuery.get());
user.increment('visits');
page.render('list');
});
});
app.get('/things', function(page, model, params, next) {
// This value is set on the server in the `createUserId` middleware
var userId = model.get('_session.userId');
// Create a scoped model, which sets the base path for all model methods
var user = model.at('users.' + userId);
// Create a mongo query that gets the current user's items
var things = model.query('things', {userId: userId});
// Get the inital data and subscribe to any updates
model.subscribe(user, things, function(err) {
if (err) return next(err);
// Create references that can be used in templates or controller methods
model.ref('_page.user', user);
things.ref('_page.things');
console.log(things.get());
user.increment('visits');
page.render('things');
});
});
// CONTROLLER FUNCTIONS //
app.fn('list.add', function(e, el) {
var newItem = this.model.del('_page.newItem');
if (!newItem) return;
newItem.userId = this.model.get('_session.userId');
this.model.add('items', newItem);
});
app.fn('list.remove', function(e) {
var item = e.get(':item');
this.model.del('items.' + item.id);
});
app.fn('things.add', function(e, el) {
var newItem = this.model.del('_page.newItem');
if (!newItem) return;
newItem.userId = this.model.get('_session.userId');
this.model.add('things', newItem);
});
app.fn('things.remove', function(e) {
var item = e.get(':item');
this.model.del('things.' + item.id);
});
<Body:>
<div class="row">
<h1>Things</h1>
<form class="span3" x-bind="submit: things.add">
<h3>Add item</h3>
<fieldset>
<label>Name</label>
<input type="text" value={_page.newItem.name}>
<label>Note</label>
<textarea>{_page.newItem.note}</textarea>
<div>
<button type="submit" class="btn">Add</button>
</div>
</fieldset>
<div class="well visits">
<b>Fun fact:</b> You've visited the list {_page.user.visits} times.
</div>
</form>
<div class="span8 offset1">
<table class="table">
<thead>
<tr>
<th>Item</th>
<th>Note</th>
</tr>
</thead>
<tbody>
{#each _page.things as :item}
<tr>
<td>{{:item.name}}</td>
<td>{{:item.note}}</td>
<td><button class="btn" x-bind="click: things.remove">Remove</button></td>
</tr>
{/}
</tbody>
</table>
</div>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment