Search code examples
javascriptjquerybackbone.jsbackbone-ui

Backbone.View not responding to Backbone.UI


I'm building a small program to allow display of some details of a group of people. There is an option to update the details. However, the updates are not being rendered by the view:

Here is my server.js:

var express= require("express"),
bodyparser= require("body-parser");

var app= express();

app.use(express.static(__dirname+ "/public"));
app.use(bodyparser.json());

app.get("/", function(req, res){
    res.render("index.jade");
});

app.listen(3002);

My index.jade is:

doctype html

link(rel="stylesheet", href="backbui.css")

#main

script(src= "jquery.js")
script(src= "underscore.js")
script(src= "backbone.js")
script(src= "laconic.js")
script(src= "moment.js")
script(src= "backbui.js")
script(src= "theapp.js")

My theapp.js file is:

var Person= Backbone.Model.extend({}),
People= Backbone.Collection.extend({});

var Genders= new Backbone.Collection(
        [
             {name: "Female", id: 1},
             {name: "Male", id: 0}
]);

var people= new People([
            {name: "John Doe", gender: Genders.get(0), birthday:
             new Date(1990, 5, 15), married: false},
            {name: "Jane Smith", gender: Genders.get(1), birthday:
             new Date(1985, 10, 10), married: true},
            {name: "Tom Smith", gender: Genders.get(0), birthday: 
             new Date(1980, 1, 20), married: true},
            {name: "Sally Fox", gender: Genders.get(1), birthday: 
             new Date(1998, 7, 31), married: false}
]);

var table= new Backbone.UI.TableView({
    model: people,  // collection can also be passed
    columns: [
        {title: "Name", content: "name"},
        {title: "Gender", content: "gender", 
         format: function(model){ return model.get("name"); }},
        {title: "Birthday", content: "birthday",
         format: function(date){ return date.toString(); }},
        {title: "Married", content: "married",
         format: function(married){ return married? "yes": "no"; }}
    ]
}); 

var sally= people.models[3];

var textbox= new Backbone.UI.TextField({
    model: sally,
    content: "name",
});

var radios= new Backbone.UI.RadioGroup({
    model: sally,
    content: "gender",
    alternatives: Genders,
    altLabelContent: "name",
});

var Appview= Backbone.View.extend({
    el: "#main",

    render: function(){
            this.$el.append(table.render().el);
            this.$el.append(textbox.render().el);
            this.$el.append(radios.render().el);
            return this;
    }
});

new Appview().render();

I want to see real-time update of 4th name in the table viz. Sally Fox when I make changes in the textbox area. Similarly I would like to see the table gender of Sally Fox change when I make the change in the radio button.

Basically I want my Backbone.TableView to listen to changes made in other Backbone.UI widgets like Backbone.UI.RadioGroup and Backbone.UI.TextField


Solution

  • You're on the right path. Add listeners in your views to listen for when changes happen to the people collection. Changes to individual models (i.e. sally) will also bubble up through the collection.

    I'm not too familiar with Backbone.UI, but the changes would go something like this:

    // Make the table listen to changes in the passed-in collection & re-render
    // when needed
    var table= new Backbone.UI.TableView({
        model: people,  // collection can also be passed
        columns: [
            {title: "Name", content: "name"},
            {title: "Gender", content: "gender", 
             format: function(model){ return model.get("name"); }},
            {title: "Birthday", content: "birthday",
             format: function(date){ return date.toString(); }},
            {title: "Married", content: "married",
             format: function(married){ return married? "yes": "no"; }}
        ],
    
        initialize: function() {
            // When a change event happens to the model/collection, re-render
            this.listenTo(model, 'change', this.render);
        }
    }); 
    

    You would do similar things for other views that you want to react to data changes. The key is to have the views share the same instance of the model/collections you're changing, and then listen for specific changes.

    If this doesn't get you going, post comments and/or a JSFiddle and we can make progress that way.