Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
View concept -- because templates and views are the same.
// THIS FILE IS A JADE FILE -- THE EXTENSION IS TO FORCE LANGUAGE INTERPRETATION
// Set up of dependencies and bindings
{
// // Specify any dependencies (e.g. partials must be defined)
// 'require': ['mvc!v/nav!v/main'],
// Backbone style event bindings -- INSIDE the view/template markup
// I like this because it is so fool-proof and quite portable
'events': {
'submit .validate-form': 'submit',
'click .submitBtn': 'submit'
},
// Backbone style methods
'submit': function (e) {
// Prevent normal submission
e.preventDefault();
// Run validation
var isValid = this.validate();
// If it is valid, emit an event
// TODO: This could be updating a model based on MVC implementation but that starts to over-blend
// TODO: We could also emit to Sauron (global mediator) like a boss
if (isValid) {
this.emit('submit-pass');
}
},
// Semantic helper for jQuery plugin
'validate': function () {
return this.$elt.validateForm();
}
}
// Note the two line breaks to separate JSON from content; using technique from toto; https://github.com/twolfson/json-content-demux
// Hyphened-classes are for CSS, camelCased are for JS
form.validate-form
label(for="name") Name
input#name.validate(type="text", placeholder="John Doe")
submit.submitBtn
// Once processed by Builder, returns a jQuery collection with bindings from JSON at start AS WELL AS build chain bindings (e.g. validateForm)
// Set up of dependencies and bindings
{
// Specify any dependencies (e.g. partials must be defined)
'require': ['mvc!v/nav!v/home']
}
// Still have the two line breaks
// Very simple markup since this is a wrapper view
partial('nav')
partial('main')
// You can also skip over the JSON declaration
h1 Home
p Welcome to the website!
// The n_home is to force order among gist files
{
'events': {
'click .nav-item': 'navigateTo'
},
'navigateTo': function (e) {
// Stop the default action
e.preventDefault();
// Determine where we want to go
var $target = $(e.target),
$a = $target.find('a'),
href = $a.attr('href');
// If we are not on the same page, emit the request
if (this.currentPage !== href) {
this.emit('navigate', href);
}
}
}
ul.nav
li.nav-item
a(href="#home") Home
li.nav-item
a(href="#about") About
li.nav-item
a(href="#contact") Contact

This gist challenges keeping template and logic separate.

From my perspective, there are two sets of logic that exist in user interfaces:

  • Interactive (the kind of bindings that perform things like animations and validation)
  • Business (updating data and talking to servers)

My current and past beliefs are that views are the content and controllers are the business logic. Content should be interactive not static -- if I click on X, then Y should happen. This binding does not belong in a controller; it is part of the markup.

Rant:

Back when our UI's were generating content on the server-side, all views were static HTML going downstream. However, once they made it to the client side, we had a single endpoint where JavaScript bindings would take place. This has since changed with client side UI's, we now have many end-points since we render and bind every view. This means we need to modularize all of those interactions with the content itself.

Pros:

  • No longer maintaining two files for one view/template combination

Cons:

  • Attaching events onto partials gets interesting but it always does
  • Goodbye linting =(
    • The caveat for this is that if anything can be abstracted to a jQuery plugin, it should be (and thus instantiated via Builder)
    • Otherwise, it will be a sad one-off fashion that cannot be linted

If you are asking, but what about using a template for two views? (in the backbone sense) My response is nothing has changed -- the only difference is instead of being a template/view difference, they are now both views. Just load the common view as a partial, problem solved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment