1

In backbone I want to have a child view that is used, destroyed and cleans up after itself. The 'cleans up after itself' I'm having a problem with understanding the correct (if there is one) way of doing. So a contrived example is:

var B = Backbone.View.extend({
    sayHello: function () {
        this.trigger('hello');
    }
});

var A = Backbone.View.extend({
    initialize: function () {
       var b = new B();

       b.listenTo(b, 'hello', function () {
            console.log('hello');
        });

        b.sayHello();

        b.remove();
    },
});

var a = new A();

This part in particular looks weird is:

b.listenTo(b, 'hello', function () {
    console.log('hello');
});

Is it normal to have a view listenTo itself? Is there a better way to do this?

Mike Davis
  • 293
  • 5
  • 12

1 Answers1

1

Technically your code should work.

Having a view listen to itself has MANY legitimate uses (in fact I wrote a whole framework on it). The primary purpose is when a View is built to be abstracted (sometimes multiple times) and needs a way to communicate with it's child views. This becomes SUPER important when you have multiple programmers who use each other's code (one is writing core components, the other is implementing the core components, yet another is taking that implementation and further extending it for his own purposes) For example:

//The Abstract Model. Programmer shouldn't have to know how animal works. The programmer
//can create models extended off of this and just subscribe it's triggers (and trigger it's own)
var Animal = Backbone.View.extend({
   initialize: function() {
      //A lot of stuff happens when an animal gets scared. But these are the 
      //things ALL Animals do
      this.listenTo(this, 'scared', function(){
         this.run();
         this.hide();
      });
   },
   //This is how ALL Animals run
   run: function (){
     console.log('Running away with tail between legs');
     //Just in case an animal does something in ADDITION to what's above they can 
     //subscribe to running and do their own extra stuff
     this.trigger('running');
   }
});

//So a programmer decided to create a cat  
var Cat = Animal.extend({
    initialize: function(){
        //A cat listens for barks (from some external source like a mediator).
        this.listenForBarks();
        //it addition to whatever happens when an Animal is scared (and any other external factors/object that choose to subscribe to it) a cat will hiss
        this.listenTo(this, 'scared', this.hiss);
        //when a cat runs it does something specific to a cat (like jumping on a garbage cans)
        this.listenTo(this, 'running', this.jumpOnGarbageCan);
    },
    //When it heads barks, it gets scared
    listenForBarks: function(){
        this.listenTo(Backbone, 'bark', function(){
            //As a programmer I don't really know how Animals react when they're scared.
            //But just in case anyone (like by Parent Object) knows or somebody else in the outside world (like a Human object) wants to know I'll broadcast it
             this.trigger('scared');
        });
    },
    hiss: function(){
        this.trigger('hiss');
        console.log('hiss');
    },
    jumpOnGarbageCan: function(){
        console.log('jump!');
    }
});


var Dog = Animal.extend({
   bark: function(){
      //a dog barks for some reason. It doesn't know what a cat is (or that the cat even exists). Just decided to bark at some point. It broadcasts it to the world (via the Mediator)
      Backbone.trigger('bark');
   }
});

The only thing I would change in your code is moving

b.listenTo(b, 'hello', function () {
   console.log('hello');
});

part into B's initialize function and replacing b (the first argument) with this (similar to how I do in my examples. If a view is listening to itself it should do it in it's own initialize function.

Toli
  • 5,547
  • 8
  • 36
  • 56
  • Thanks! It sounds similar to my use case. To explain a little more, the reason `b` is subscribing to itself inside `a` is `B` will be re-used and the handler will be different depending where it is used. Would there be a reason to do `this.listenTo` inside `a`'s `initialize` rather than `b.listenTo`? – Mike Davis Jul 16 '14 at 16:05
  • @MikeDavis well if the action is being managed by A (i.e. A is the one who has the code for the action then A should be the one listening (a.listenTo(b)). Sorry no backtick on my tablet. I'll explain when I am back from vacation. – Toli Jul 18 '14 at 14:10