Backbone.js: Nested model

by kwon

HTML

<script src="http://documentcloud.github.com/underscore/underscore.js"></script>
<script src="http://documentcloud.github.com/backbone/backbone.js"></script>
<script src="http://documentcloud.github.com/backbone/examples/backbone-localstorage.js"></script>
<script src="https://raw.github.com/PaulUithol/Backbone-relational/master/backbone-relational.js"></script>
<section id="restaurant_menu">
    <h1>Menu for <span class='restaurant_name'></span></h1>
    <button class="new_menu_type">New Menu Type</button>
    <ol class="menu_types"></ol>
</section>

<section class="form_views"></section>

<script type="text/html" id="menu_type_item_tpl">
    <h1>Menu Item</h1>
    <nav>
        <a href="#" class="new_menu_category">Add Menu Category</a>
        |
        <a href="#" class="destroy_type">X</a>
    </nav>
    <ol class="menu_categories"></ol>
</script>

<script type="text/html" id="menu_category_item_tpl">
    <h1>Menu Category</h1>
    <nav>
        <a href="#" class="new_menu_item">Add Menu Item</a>
        |
        <a href="#" class="destroy_category">X</a>
    </nav>
    <ol class="menu_items"></ol>
</script>

<script type="text/html" id="menu_item_item_tpl">
    <h1>Menu Item</h1>
    <nav>
        <a href="#" class="destroy_item">X</a>
    </nav>
</script>

<!-- form templates -->
<script type="text/html" id="new_menu_type_tpl">
    <h1>New Menu Type</h1>
    <input type="text" name="menu_type_name" />
    <button>Save</button>
</script>
        
<script type="text/html" id="new_menu_category_tpl">
    <h1>New Menu Category <span class="menu_type_name"><span></h1>
    <input type="text" name="menu_category_name" />
    <button>Save</button>
</script>
        
<script type="text/html" id="new_menu_item_tpl">
    <h1>New Menu Item <span class="menu_category_name"><span></h1>
    <input type="text" name="menu_item_name" />
    <button>Save</button>
</script>

SCSS

ol {
    list-style-type: decimal;
    margin-left: 25px;
}

#restaurant_menu {
    float: left;
    width: 50%;
    height: 350px;
    overflow-y: auto;
}

.form_views {
    background-color: #efefef;
    float: left;
    width: 50%;
}

JavaScript

// Models
var Restaurant = Backbone.Model.extend({
    localStorage: new Store("restuarant"),
    initialize: function() {
        this.menu_types = new MenuTypes();
    },
    parse: function(response) {
        console.log('parse');
        return response;
    }
});
var MenuType = Backbone.Model.extend({
    localStorage: new Store("menutypes"),
    initialize: function() {
        this.menu_categories = new MenuCategories;
    }
});
var MenuCategory = Backbone.Model.extend({
    localStorage: new Store("menucategories"),
    initialize: function() {
        this.menu_items = new MenuItems;
    }
});
var MenuItem = Backbone.Model.extend({
    localStorage: new Store("menuitems")
});

// Collection
var MenuTypes = Backbone.Collection.extend({
    model: MenuType,
    localStorage: new Store("menutypes")
});
var MenuCategories = Backbone.Collection.extend({
    model: MenuCategory,
    localStorage: new Store("menucategories")
});
var MenuItems = Backbone.Collection.extend({
    model: MenuItem,
    localStorage: new Store("menuitems")
});
// initialize collections
//var menu_types = new MenuTypes;
//var menu_categories = new MenuCategories;




// Line views
var MenuTypeView = Backbone.View.extend({
    tagName: "li",
    template: _.template($("#menu_type_item_tpl").html()),
    events: {
        'click .new_menu_category': 'new_menu_category',
        'click .destroy_type': 'destroy'
    },
    initialize: function() {
        this.model.bind('destroy', this.remove, this);
        this.model.menu_categories.bind('add', this.add_menu_category, this);
        this.render();
    },
    render: function() {
        $(this.el).html(this.template());
        this.$("h1").text(this.model.get('name'));
        return this;
    },
    new_menu_category: function(evt) {
        console.log("new menu category...");
        var form = new MenuCategoryFormView({
            model: new MenuCategory({menu_type: this.model})
        });
       ...