Vijay Singh
Vijay Singh

Reputation: 277

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

Upvotes: 0

Views: 70

Answers (2)

Vijay Singh
Vijay Singh

Reputation: 277

While the answer given by Peter (above) is also correct, we can also make the changes directly in the backbone-ui.js library file:

Inside the initialize method for tableview (search for tableview in the file backbone-ui.js, find its initialize function) add:

this.model.on("change", this.render, this);

and you'll be fine. (You may want to add the same line inside the initialize method of the list property of backbone-ui.js file to get responsive views for lists)

Upvotes: 0

Peter Wagener
Peter Wagener

Reputation: 2092

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.

Upvotes: 1

Related Questions