title: Backbone.js | How can I store elements of a view for retrieval later?
body: <p>This is my first attempt at using Backbone.js, so I decided to make a simple test application that simulates a restaurant menu with menu items.  I was following along with <a href="http://andyet.net/blog/2010/oct/29/building-a-single-page-app-with-backbonejs-undersc/" rel="nofollow">this cool blog post from andyet.net</a>.</p>
  
  <p>I'm having a problem when adding a model to a collection.  I have bound a view method to the collection's add event that should update the view.  Here is the code with as much irrelevant code removed as possible.</p>
  
  <p><em>(note: I removed things like local scope <code>var</code> declarations and closures for the sake of brevity.  The following is still a little long, and I know that's annoying, but it should be pretty straightforward and easy to understand):</em></p>
  
  <pre><code>MenuItem = Backbone.Model.extend({
      // initialize functions removed for brevity
  });
  Menu = Backbone.Model.extend({
      // initialize functions removed for brevity
      // MenuSelection property is defined here.
  });
  MenuSelection = Backbone.Collection.extend({ model: MenuItem });
  MenuItemView = Backbone.View.extend({
      // render template
  });
  
  /**
   * This is unaltered from the code.  The error occurs here.
   */
  RestaurantAppView = Backbone.View.extend({
      addMenuItem : function (MenuItem) {
          var view = new MenuItemView({ model : MenuItem });
          this.menuList.append(view.render().el);
          // ERROR occurs here.  error: "this.menuList is undefined"
      },
      initialize : function () {
          this.model.MenuSelection.bind('add', this.addMenuItem);
      },
      render : function () {
          $(this.el).html(ich.app(this.model.toJSON()));
          this.menuList = this.$('#menuList'); // IT IS DEFINED HERE
          return this;
      }
  });
  
  /**
   * Everything after this I left in just-in-case you need to see it.
   */
  RestaurantAppController = {
      init : function (spec) {
          this.config = { connect : true };
          _.extend(this.config, spec);
          this.model = new Menu({
             name : this.config.name,
          });
          this.view = new RestaurantAppView({ model : this.model });
          return this;
      }
  };
  $(function() {
      // simulating ajax JSON response.
      var json = {
          Menu : {
              name : 'Appetizers',
              MenuItem : [
                  {
                      name : 'toast',
                      description : 'very taosty',
                      price : '$20.00'
                  },
                  {
                      name : 'jam',
                      description : 'very jammy',
                      price : '$10.00'
                  },
                  {
                      name : 'butter',
                      description : 'very buttery',
                      price : '$26.00'
                  }
              ]
          }
      };
      window.app = RestaurantAppController.init({
          name : json.Menu.name
      });
      $('body').append(app.view.render().el);
      app.model.MenuSelection.add(json.Menu.MenuItem);
  });  
  </code></pre>
  
  <p>I've marked with comments the problematic area.  According the the <a href="http://documentcloud.github.com/backbone/#View-dollar" rel="nofollow">Backbone Documentation</a>:  </p>
  
  <blockquote>
    <p>If jQuery or Zepto is included on the page, each view has a $ function that runs queries scoped within the view's element.  </p>
  </blockquote>
  
  <p>So, if I'm setting <code>this.menuList = this.$('#menuList');</code> in the render method, why can I not access <code>this.menuList</code> in the <code>addMenuItem</code> method?  The demo I linked to at the top does it exacly like this.  Also, if I swap out <code>this.menuList</code> for a jQuery selector, like so:</p>
  
  <pre><code>addMenuItem : function (MenuItem) {
      var view = new MenuItemView({ model : MenuItem });
      $('#menuList').append(view.render().el);
  }
  </code></pre>
  
  <p>Everything works fine.  But I don't <strong>want</strong> to re-select the menulist ID every time <code>addMenuItem</code> is executed.  The RightWay<sup>TM</sup> is to cache it after it is rendered.</p>
  
  <p>Also note:  I thought maybe the problem was with the ICanHaz template not returning fast enough, but then <code>this.menuList</code> would be an empty array, not <code>undefined</code>, so that's not it.</p>