Skip to content

Instantly share code, notes, and snippets.

@anorgan
Last active December 23, 2015 09:29
Show Gist options
  • Save anorgan/6615274 to your computer and use it in GitHub Desktop.
Save anorgan/6615274 to your computer and use it in GitHub Desktop.
A Pen by Marin Crnković.

Testing backbone relational

CodePen

<meta http-equiv="content-type" content="text/html;charset=UTF-8">
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0/handlebars.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone-relational/0.8.5/backbone-relational.min.js"></script>
<!-- script src="https://raw.github.com/PaulUithol/Backbone-relational/master/backbone-relational.js"></script -->
<div class="container">
<h1>Shopping List</h1>
</div>
<!-- Templates -->
<script type="text/x-handlebars-template" id="shopping-list">
<h1>{{ title }}</h1>
</script>
<script type="text/x-handlebars-template" id="group">
<h2>{{ title }}</h2>
<ul class="ingredients list-unstyled list-inline">
</ul>
</script>
<script type="text/x-handlebars-template" id="ingredient">
<div class="col-lg-2">
<input type="checkbox" {{#if checked }}checked="checked"{{/if}} >
</div>
<div class="col-lg-5">
<p>
{{ title }}
</p>
</div>
<div class="col-lg-2">
<input type="text" class="" name="quantity" value="{{ quantity }}">
</div>
</script>
var app = {};
$(document).ready(function() {
// Models
$.ShoppingList_Ingredient = Backbone.RelationalModel.extend({
});
$.ShoppingList_Group = Backbone.RelationalModel.extend({
defaults: {
title: 'New shopping list group',
},
relations: [{
type: Backbone.HasMany,
key: 'ingredients',
relatedModel: '$.ShoppingList_Ingredient',
collectionType: 'IngredientCollection',
reverseRelation: {
key: 'group',
includeInJSON: 'id'
}
}]
});
$.ShoppingList = Backbone.RelationalModel.extend({
defaults: {
title: 'New shopping list',
},
relations: [{
type: Backbone.HasMany,
key: 'groups',
relatedModel: '$.ShoppingList_Group',
collectionType: 'GroupCollection',
reverseRelation: {
key: 'shopping_list',
includeInJSON: 'id'
}
}]
});
// Collections
IngredientCollection = Backbone.Collection.extend({
model: $.ShoppingList_Ingredient
});
GroupCollection = Backbone.Collection.extend({
model: $.ShoppingList_Group
});
var Groups = Backbone.Collection.extend({
model: $.ShoppingList_Group
});
// Views
$.ShoppingListView = Backbone.View.extend({
el: $(".container"),
initialize: function()
{
_.bindAll(this, 'render');
this.model.bind('change', this.render);
this.model.bind('add:groups', this.render);
this.model.bind('remove:groups', this.render);
this.render();
},
template: Handlebars.compile($('#shopping-list').html()),
render: function()
{
// Remove "old" groups
this.$el.html(this.template(this.model.toJSON()));
// Get all groups, render them
_.each(this.model.get('groups').models, function (group) {
this.renderGroup(group);
}, this);
return this;
},
renderGroup: function(group)
{
var groupView = new GroupView({
model: group
});
$(this.$el).append(groupView.render().el);
}
});
GroupView = Backbone.View.extend({
tagName: 'div',
className: "well group",
initialize: function () {
_.bindAll(this, 'render');
this.model.bind('change', this.render);
this.model.bind('add:ingredients', this.render);
this.model.bind('remove:ingredients', this.render);
this.render();
},
template: Handlebars.compile($('#group').html()),
render: function()
{
this.$el.html(this.template(this.model.toJSON()));
// Hate this!
_.each(this.model.get('ingredients').models, function (ingredient) {
this.renderIngredient(ingredient);
}, this);
return this;
},
renderIngredient: function(ingredient)
{
var ingredientView = new IngredientView({
model: ingredient
});
$(this.$el).find('ul.ingredients').append(ingredientView.render().el);
}
});
IngredientView = Backbone.View.extend({
tagName: 'li',
className: "ingredient",
initialize: function () {
_.bindAll(this, 'render');
this.render();
},
template: Handlebars.compile($('#ingredient').html()),
render: function()
{
this.$el.html(this.template(this.model.toJSON()));
return this;
},
});
/*
* Run
*/
// Inst shopping list
app.shoppingList = new $.ShoppingList({
title: 'Super shopping lista'
});
// Inst first group, add it to the list
app.group = new $.ShoppingList_Group({
title: 'Nova grupa'
});
app.shoppingList.get('groups').add(app.group);
// Inst a couple of ingredients, add to group
app.ingredient1 = new $.ShoppingList_Ingredient({
title: 'Jabuka',
quantity: 3,
checked: false
});
app.ingredient2 = new $.ShoppingList_Ingredient({
title: 'Kruška',
quantity: 2,
checked: true
});
app.group.get('ingredients').add([app.ingredient1, app.ingredient2]);
app.shoppingListView = new $.ShoppingListView({model: app.shoppingList});
console.log(JSON.stringify(app.shoppingList.toJSON(), null, '\t'));
// Add group
var secondGroup = new $.ShoppingList_Group({title: 'Second group'});
app.shoppingList.get('groups').add(secondGroup);
// Add ingredients
secondGroup.get('ingredients').add({title: 'Eggs', checked: true, quantity: 12});
secondGroup.get('ingredients').add({title: 'Answer to The Ultimate Question of Life, the Universe, and Everything', checked: false, quantity: 42});
});
@import url(//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment