Skip to content

Instantly share code, notes, and snippets.

@jgonggrijp
Last active February 15, 2019 22:10
Show Gist options
  • Save jgonggrijp/246cc454a0f1b7d19fb76fdca9a2f171 to your computer and use it in GitHub Desktop.
Save jgonggrijp/246cc454a0f1b7d19fb76fdca9a2f171 to your computer and use it in GitHub Desktop.
The images from backbonejs.org/#Getting-started with example code for @UUDigitalHumanitieslab/cookiecutter-webapp-deluxe

Backbone illustrated with modern code examples

This files takes the images from the getting started section of backbonejs.org and combines them with TypeScript code examples that fit the tools and conventions used in cookiecutter-webapp-deluxe.

Models and Views

Models and Views diagram

This image shows a five-step series of events.

  1. "Input" arrow: user clicks on a button.
  2. "Data" arrow: view sends updated data to the model.
  3. "Sync" arrow: model sends a request to the server and receives a response.
  4. "Change" broadcast: model updates itself and triggers the change event.
  5. "Render" arrow: view responds to the change event by rendering itself.

These steps are highlighted in the example code below.

import { extend } from 'lodash';

import Model from '../core/model';
import View from '../core/view';
import bookTemplate from './bookDisplay-template';

// All Model subclasses implement step 4 out of the box.
class Book extends Model {}

class BookDisplay extends View {
    initialize() {
        // The next line ensures that step 5 always happens after 4.
        this.listenTo(this.model, 'change', this.render);
    }
    render() {
        // This is the implementation of step 5.
        this.$el.html(this.template(this.model.toJSON()));
        return this;
    }
    markRead() {
        // The following line implements steps 2 and 3 and
        // immediately triggers step 4.
        this.model.save({read: true});

        // We can delay step 4 until the server has confirmed the
        // change by adding the second `options` argument like below.
        this.model.save({read: true}, {wait: true});
    }
}

extend(BookDisplay.prototype, {
    template: bookTemplate,
    events: {
        // This line enables step 1: react to DOM events.
        'click button': 'markRead',
    },
});

let book = new Book({
    title: 'Alice in Wonderland',
    author: 'Lewis Carroll',
    read: false,
});

let display = new BookDisplay({model: book});

// The next line also enables step 1: make display visible to user.
display.render().$el.appendTo('body');

Below, we illustrate a few phrases from the Models and Views section in the Backbone documentation with additional example code.

Model

  • Loads and saves from the server.
// loads
book.fetch(...);

// saves
book.save(...);

// deletes
book.destroy(...);
  • Emits events when data changes.
book.set(...);
book.unset(...);
book.clear();
// triggers 'change:title' if the title changed
// triggers 'change'       if any attribute changed
// .set can also call this.validate(...) if you pass the {validate: true} option

book.fetch(...);
// triggers 'request' immediately
// calls this.set(...) if the request is successful, which may trigger 'change'
// triggers 'error' if the request fails

book.save(...);
// calls this.validate(...), which may trigger 'invalid' (and prevent the rest)
// triggers 'request' immediately
// calls this.set(...) immediately unless you pass {wait: true}
// triggers 'sync' if the request is successful
// calls this.set(...) after server confirmation if you pass {wait: true}
// triggers 'error' if the request fails

book.destroy(...);
// triggers 'request' immediately
// triggers 'destroy' if the request is successful
// triggers 'error' if the request fails

View

  • Handles user input and interactivity.
class BookDisplay extends View {
    // ...
    markRead(event) {
        this.model.save({read: true});
    }
    showNext(event) {
        event.preventDefault();
        this.trigger('next');  // let somebody else do the work
    }
}

extend(BookDisplay.prototype, {
    // ...
    events: {
        'click button': 'markRead',
        'click a.next': 'showNext',
    },
});

A Model manages an internal table of data attributes,

// The actual internal table. You shouldn't use this directly, but it
// can be useful during debugging.
book.attributes

// Safely get the value of a single attribute.
book.get('title');

// Or get it HTML-escaped.
book.escape('title');

// Check whether an attribute is set.
book.has('title');

// Safely set the value of a single attribute.
book.set('read', true);

// Safely set multiple values at once.
book.set({
    title: 'Wuthering Heights',
    author: 'Emily Brontë',
});

// Get a JSON-serializable copy of the attributes.
book.toJSON();

Collections

Work in progress.

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