¿Qué es BackboneJS? Primeros pasos

Hecho esto, ahora vamos con nuestro proyecto. Se trata de un formulario de selección de servicios con Backbone.js, que le permite elegir un conjunto de elementos de una lista. Un campo de precio total se calculará de manera automática tomando el precio de los servicios. que seleccionemos. El elemento principal en la página será por tanto el formulario que contendrá una lista de elementos para los servicios:

 

<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8" />
        <title>Tu primera aplicación con Backbone.js App</title>

        <!-- Google web fonts -->
        <link href="http://fonts.googleapis.com/css?family=PT+Sans:400,700" rel='stylesheet' />

        <!-- The main CSS file -->
        <link href="assets/css/style.css" rel="stylesheet" />

    </head>

    <body>

        <form id="main" method="post" action="submit.php">
            <h1>My Services</h1>

            <ul id="services">
                <!-- The services will be inserted here -->
            </ul>

            <p id="total">total: <span>$0</span></p>

            <input type="submit" id="order" value="Order" />

        </form>

        <!-- JavaScript Includes -->
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
        <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
        <script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>

        <script src="assets/js/script.js"></script>

    </body>
</html>

 

Como puedes ver, al finalizar nuestro formulario es donde luego añadimos las diferentes librerías que utilizaremos además de la propia de Backbone o Underscore que nos ayudará a dotar de funciones al formulario.

Vamos ahora con la parte del programar nuestro JavaScript. Lo primero que haremos será crear un nuestro modelo de servicio que contendrá las propiedades para el nombre del servicio, precio y un campo de estado para saber si este servicio está seleccionado o no.

A partir de aquí se creará un objeto de esta clase para cada servicio que ofrecemos en el formulario y almacenaremos todos los sevicios en una colección Backbone. La idea de fondo es que a partir de una lista predeterminada nuestra aplicación pueda escuchar los eventos que se produzcan (que se generan cada vez que se actualiza la propiedad marcada) y actualizar la vista de nuestra aplicación.

assets/js/script.js

$(function(){

    // Create a model for the services
    var Service = Backbone.Model.extend({

        // Will contain three attributes.
        // These are their default values

        defaults:{
            title: 'My service',
            price: 100,
            checked: false
        },

        // Helper function for checking/unchecking a service
        toggle: function(){
            this.set('checked', !this.get('checked'));
        }
    });

    // Create a collection of services
    var ServiceList = Backbone.Collection.extend({

        // Will hold objects of the Service model
        model: Service,

        // Return an array only with the checked services
        getChecked: function(){
            return this.where({checked:true});
        }
    });

    // Prefill the collection with a number of services.
    var services = new ServiceList([
        new Service({ title: 'web development', price: 200}),
        new Service({ title: 'web design', price: 250}),
        new Service({ title: 'photography', price: 100}),
        new Service({ title: 'coffee drinking', price: 10})
        // Add more here
    ]);

    // This view turns a Service model into HTML. Will create LI elements.
    var ServiceView = Backbone.View.extend({
        tagName: 'li',

        events:{
            'click': 'toggleService'
        },

        initialize: function(){

            // Set up event listeners. The change backbone event
            // is raised when a property changes (like the checked field)

            this.listenTo(this.model, 'change', this.render);
        },

        render: function(){

            // Create the HTML

            this.$el.html('<input type="checkbox" value="1" name="' + this.model.get('title') + '" /> ' + this.model.get('title') + '<span>$' + this.model.get('price') + '</span>');
            this.$('input').prop('checked', this.model.get('checked'));

            // Returning the object is a good practice
            // that makes chaining possible
            return this;
        },

        toggleService: function(){
            this.model.toggle();
        }
    });

    // The main view of the application
    var App = Backbone.View.extend({

        // Base the view on an existing element
        el: $('#main'),

        initialize: function(){

            // Cache these selectors
            this.total = $('#total span');
            this.list = $('#services');

            // Listen for the change event on the collection.
            // This is equivalent to listening on every one of the 
            // service objects in the collection.
            this.listenTo(services, 'change', this.render);

            // Create views for every one of the services in the
            // collection and add them to the page

            services.each(function(service){

                var view = new ServiceView({ model: service });
                this.list.append(view.render().el);

            }, this);   // "this" is the context in the callback
        },

        render: function(){

            // Calculate the total order amount by agregating
            // the prices of only the checked elements

            var total = 0;

            _.each(services.getChecked(), function(elem){
                total += elem.get('price');
            });

            // Update the total price
            this.total.text('$'+total);

            return this;
        }
    });

    new App();

});

 

Como se puede ver el programa tiene un poco de “truco” ya que tenemos que extender las clases proporcionadas por Backbone y anular los métodos que deseamos realizar de una manera diferente. Pero esto también es un buen ejemplo de hasta qué punto este Framework nos permite hacer lo que queramos gracias a su flexibilidad.

La vista principal de nuestra aplicación es App, que está vinculada al formulario #main, inicializa las otras vistas y actualiza el precio total en su método de representación.

Lo que nos queda ahora es poner todo a funcionar y para manejar los envíos desde el formulario vamos a necesitar añadir una línea de PHP. Todo lo que hace es imprimir los nombres de los campos de casilla seleccionados:

submit.php

echo htmlspecialchars(implode(array_keys($_POST), ', '));

 

Y ya lo tenemos. El último paso sería ya personalizar nuestra aplicación mediante CSS pero esa parte ya es algo que va más a gusto de cada uno. Lo importante es que con estos pasos nuestro formulario de selección de servicios desarrollado con Backbone ya está listo.

Como ves es un ejemplo muy sencillo y espero que lo encuentres útil para entender y tener una buena visión general de este framework.