Making a To-Do List With flatiron.js (Story 5)

Friday, January 13th 2012
The flatiron library is no more. So, other than reading stuff, there just isn't all that much relevant stuff, here.

This post continues the creation of a to-do list with flatiron.js.

Previous Stories in this Series

Last but not least: we need to allow the user to delete a listed item. So, we can change the template used to create the list items to include a delete button. Here’s what I have, simple and ugly.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
app.router.get('/', function() {
var self = this;
fs.readFile('index.html', function(err, data) {
if(err) {
self.res.writeHead(404);
self.res.end();
return;
}
var listContent = "";
var listItemTemplate = '<button>Delete Item</button>' +
'<span id="ctime" class="ctime"></span>' +
'I need to <span id="desc" class="desc"></span>' +
'<input type="hidden" name="method" value="DELETE" />' +
'<input type="hidden" id="id" name="id" value="" />';
if(typeof self.req.session.tasks === 'undefined') {
self.req.session.tasks = [];
}
var options = {
'id': ['id', 'value'],
'ctime': 'id',
'desc': 'id'
};
self.req.session.tasks.forEach(function(task) {
var data = {
'desc': task.desc,
'ctime': new Date(task.ctime).toDateString().substr(4),
'id': task._id
};
listContent += '<li>' +
'<form method="post" action="/">' +
plates.bind(listItemTemplate, data, options) +
'</form>' +
'</li>';
});
data = plates.bind(data, {'task-list': listContent});
self.res.writeHead(200, {'Content-Type': 'text/html'});
self.res.end(data);
})
});

Now, we need to take into account the post for that Delete button. Because we have made this a POST, we can handle it in the POST handler that we defined in Story 3.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
app.router.post('/', function() {
var self = this;
if(self.req.body.method && self.req.body.method === "DELETE") {
var taskId = self.req.body.id;
var task = Task.get(taskId);
var tasks = self.req.session.tasks;
tasks = tasks.splice(0, tasks.indexOf(task)).concat(tasks.splice(1));
self.req.session.tasks = tasks;
Task.destroy(taskId);
} else {
var task = new (Task)({desc: self.req.body.desc});
if(task.validate().valid) {
task.save();
if(!self.req.session.tasks) {
self.req.session.tasks = [];
}
self.req.connection = {encrypted: false};
self.res.emit('header');
self.req.session.tasks.push(task);
}
}
self.res.writeHead(303, {'Location': '/'});
self.res.end();
});

And, that’s it. Everything works. It’s not pretty: the UI, the code. It would be nice to convert the POST that destroys a task into a DELETE message; however, that’s deeper than this article should go.

And, obviously, plates leaves a lot to be desired. I actually had a different implementation in my GET handler for this story and found that plates falls apart with its “simple” (read: buggy) HTML parser. I would like a DOM to actually handle this; however, as they mention in the documentation, those options do not perform quickly enough.

But, this is it: flatiron. Overall, I like its unobtrusive nature. I think I will find it easy to build applications atop this framework.

And, here’s the completed code.