Core Systems Transformation Solutions
Backbone & Marionette
Tutor: Dmitry Grachikov, ROI
1
Return on Intelligence, Inc. ©2014
All Rights Reserved.
"Simple" Frontend Application
var html = "<div>" +
"<span>" + data + "</span>" +
"</div>";
$('#container').html(html);
$('#contaner').append(
$('<div></div>').append(
$('<span></span>').html(data)
)
);
$('span').on('click', function(e) {
// do something...
$(this).addClass('some-class');
// do something again...
});
2
Return on Intelligence, Inc. ©2014
All Rights Reserved.
"Simple" Frontend Application
Benefits:
• Easy for small amount of code
• "Fast" development
Drawbaks:
• Complexity grows very fast
• Hard to understand for medium and large codebase
• Specifically to JavaScript: "Callback-Hell"
• Hard to maintain
• Tight coupling with HTML
• …
3
Return on Intelligence, Inc. ©2014
All Rights Reserved.
"Simple" Frontend Application
Benefits:
• Easy for small amount of code
• "Fast" development
Drawbaks:
• Complexity grows very fast
• Hard to understand for medium and large codebase
• Specifically to JavaScript: "Callback-Hell"
• Hard to maintain
• Tight coupling with HTML
• …
4
Return on Intelligence, Inc. ©2014
All Rights Reserved.
"Simple" Application Improvements
• Assume that "simple" approach with jQuery cannot solve all problems
• Separate View from business logic
– Solve problem with custom solution
– Using effective architectural pattern (for example MVC, MVVM,
…)
• Create own realization
• Use proven framework
5
Return on Intelligence, Inc. ©2014
All Rights Reserved.
"Simple" Application Improvements
• Assume that jQuery can't solve all problems
• Separate View from business logic
– Solve problem with custom solution
– Using effective architectural pattern (for example MVC, MVVM,
…)
• Create own realization
• Use proven framework
6
Return on Intelligence, Inc. ©2014
All Rights Reserved.
"Simple" Application Improvements
• Assume that jQuery can't solve all problems
• Separate View from business logic
– Solve problem with custom solution
– Using effective architectural pattern (for example MVC, MVVM,
…)
• Create own realization
• Use proven framework
7
Return on Intelligence, Inc. ©2014
All Rights Reserved.
"Simple" Application Improvements
• Assume that jQuery can't solve all problems
• Separate View from business logic
– Solve problem with custom solution
– Using effective architectural pattern (for example MVC, MVVM,
…)
• Create own realization
• Use proven framework
8
Return on Intelligence, Inc. ©2014
All Rights Reserved.
"Simple" Application Improvements
• Assume that jQuery can't solve all problems
• Separate View from business logic
– Solve problem with custom solution
– Using effective architectural pattern (for example MVC, MVVM,
…)
• Create own realization
• Use proven framework
9
Return on Intelligence, Inc. ©2014
All Rights Reserved.
"Simple" Application Improvements
• Assume that jQuery can't solve all problems
• Separate View from business logic
– Solve problem with custom solution
– Using effective architectural pattern (for example MVC, MVVM,
…)
• Create own realization
• Use proven framework
10
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Proven Framework vs Custom Solution
Custom Solution Proven Framework
+ Suitable to the project
+ No time for learning
- Implementation take a long time
- After a while can be that new
concepts cannot be added
+ Ready to use
+ Well documented
+ Community
- Requires time for learning
- Can take a time to figure out that
framework is not suitable to the
project
11
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Backbone.js Marionette.js
Models Collections
Views
ItemView
CollectionView
CompositeView
LayoutView
12
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Backbone.js
Backbone.js gives structure to web application
13
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Backbone.js Model Definition
var EmployeeModel = Backbone.Model.extend({
defaults: {
id: null,
name: null,
surname: null,
dateOfEmployment: null,
...
}
});
var employee = new EmployeeModel({
name: 'John',
surname: 'Johnson',
dateOfEmployment: '2000-01-05',
...
});
14
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Backbone.js Model Initialization
var EmployeeModel = Backbone.Model.extend({
defaults: {
id: null,
name: null,
surname: null,
dateOfEmployment: null,
...
}
});
var employee = new EmployeeModel({
name: 'John',
surname: 'Johnson',
dateOfEmployment: '2000-01-05',
...
});
15
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Backbone.js Model Events
employee.on('change', function(model) {
console.log('Employee changed');
});
employee.on('change:name', function(model) {
console.log('Name changed ' +
model.previous('name') + ' -> ' +
model.get('name'));
});
employee.set('name', 'Peter');
employee.set({
name: 'John',
surname: 'Peterson'
});
16
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Backbone.js Model Events
employee.on('change', function(model) {
console.log('Employee changed');
});
employee.on('change:name', function(model) {
console.log('Name changed ' +
model.previous('name') + ' -> ' +
model.get('name'));
});
employee.set('name', 'Peter');
employee.set({
name: 'John',
surname: 'Peterson'
});
17
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Backbone.js Models REST
var EmployeeModel = Backbone.Model.extend({
urlRoot: 'http://api.dev/employees',
...
});
var employee = new EmployeeModel({
name: 'John',
surname: 'Johnson',
...
});
employee.save({
...
});
urlRoot
00020000009222iik0
18
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Backbone.js Models REST
var EmployeeModel = Backbone.Model.extend({
urlRoot: 'http://api.dev/employee',
...
});
var employee = new EmployeeModel({
name: 'John',
surname: 'Johnson',
...
});
employee.save({
...
});
urlRoot
POST /employee
Response: {
"id": 1,
...
}
19
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Backbone.js Models REST
employee.fetch();
employee.save({
name: "Some name",
...
});
employee.destroy();
GET /employee/1
PUT /employee/1
{
"name": "Some name",
...
}
DELETE /employee/1
20
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Backbone.js Collection Definition
var EmployeeCollection = Backbone.Collection.extend({
model: EmployeeModel
});
var employees = new EmployeeCollection([
{id: 1, name: 'John', surname: 'Johnson'},
{id: 2, name: 'Peter', surname: 'Peterson'}
]);
21
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Backbone.js Collection Initialization
var EmployeeCollection = Backbone.Collection.extend({
model: EmployeeModel
});
var employees = new EmployeeCollection([
{id: 1, name: 'John', surname: 'Johnson'},
{id: 2, name: 'Peter', surname: 'Peterson'}
]);
22
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Backbone.js Filling Collection
employees.add({id: 1, name: 'John', ...});
or
employees.add(employee);
23
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Backbone.js Remove Data From Collection
employees.remove(1); //remove by id
or
employees.remove(employee); //remove by model
24
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Backbone.js Access Collection Data
var first = employees.first();
var second = employees.at(1); //Get second element
var peter = employees.get(2); //Search by id
var john = employees.findWhere({name: 'John'});
var johns = employees.where({name: 'John'});
25
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Backbone.js Collection Events
employees.on('add', function(model, collection) {
console.log('New employee added');
});
employees.on('remove', function(model, collection) {
console.log('Employee removed');
});
26
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Backbone.js Collections REST
var Employees = Backbone.Collection.extend({
url: 'http://api.dev/employees',
...
});
Define url
27
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Backbone.js Collections REST
employees.fetch();
employees.create({
name: "Ivan",
name: "Petrov"
});
employees.at(0).destroy();
GET /employees
POST /employees
{
"name": "Ivan",
...
}
DELETE /employees/:id
28
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Backbone.js View Definition
Backbone View
29
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Backbone.js View Definition
var EmployeeView = Backbone.View.extend({
el: 'table tbody',
render: function() {
var templateEl = '#template',
template = _.template(templateEl.html()),
html = template({users: this.collection});
this.$el.html(html);
}
});
30
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Backbone.js Template
<script type="text/template" id="template">
<% users.each(function(user) { %>
<tr>
<td><%= user.get('id') %></td>
<td><%= user.get('name') %></td>
<td><%= user.get('surname') %></td>
<td><%= user.get('position') %></td>
<td><%= user.get('dateOfEmployment') %></td>
</tr>
<% }) %>
</script>
31
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Backbone.js View Render
var employees = new EmployeeCollection(...);
var view = new EmployeeView({
collection: employees
});
view.render();
32
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js
Marionette.Js
Marionette simplifies your Backbone application
code with robust views and architecture solutions.
33
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js ItemView Definition
var EmployeeItemView = Marionette.ItemView.extend({
el: 'table tbody',
template: '#template-user'
});
34
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js ItemView vs Backbone View
var EmployeeItemView = Marionette.ItemView.extend({
el: 'table tbody',
template: '#template-user'
});
var EmployeeView = Backbone.View.extend({
el: 'table tbody',
render: function() {
var templateEl = '#template',
template = _.template(templateEl.html()),
html = template({users: this.collection});
this.$el.html(html);
}
});
35
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js ItemView Template
<script type="text/template" id="template-user">
<tr>
<td><%= id %></td>
<td><%= name %></td>
<td><%= surname %></td>
<td><%= position %></td>
<td><%= dateOfEmployment %></td>
<td>
<a href="#" class="promote">
Promote
</a>
</td>
</tr>
</script>
36
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js ItemView. Add UI Element
var EmployeeItemView = Marionette.ItemView.extend({
...
ui: {
promote: '.promote'
},
events: {
'click @ui.promote': 'onPromoteClick'
},
modelEvents: {
'change': 'render'
},
onPromoteClick: function(e) {
e.preventDefault();
this.model.set('position', 'Senior Developer');
}
});
37
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js ItemView. Add Click Handling
var EmployeeItemView = Marionette.ItemView.extend({
...
ui: {
promote: '.promote'
},
events: {
'click @ui.promote': 'onPromoteClick'
},
modelEvents: {
'change': 'render'
},
onPromoteClick: function(e) {
e.preventDefault();
this.model.set('position', 'Senior Developer');
}
});
38
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js ItemView. Add Model Change Render
var EmployeeItemView = Marionette.ItemView.extend({
...
ui: {
promote: '.promote'
},
events: {
'click @ui.promote': 'onPromoteClick'
},
modelEvents: {
'change': 'render'
},
onPromoteClick: function(e) {
e.preventDefault();
this.model.set('position', 'Senior Developer');
}
});
39
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js ItemView Initialization
var employee = new EmployeeModel(...);
var view = new EmployeeItemView({
model: employee
});
view.render();
40
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js CollectionView Definition
var CollectionView = Marionette.CollectionView.extend({
el: 'table tbody',
childView: EmployeeItemView
});
41
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js CollectionView Initialization
var employees = new EmployeeCollection();
var view = new CollectionView({
collection: employees
});
view.render();
42
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js CompositeView Definition
CompositeView = CollectionView + ItemView
43
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js CompositeView Definition
var CompositeView = Marionette.CompositeView.extend({
el: 'div#users',
template: '#template',
childView: EmployeeItemView,
childViewContainer: 'table tbody'
});
44
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js CompositeView Template
<script type="text/template" id="template">
<table class="table">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Surname</th>
<th>Position</th>
<th>Date of employment</th>
<th>Action</th>
</tr>
</thead>
<tbody>

</tbody>
</table>
</script>
45
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js CompositeView ChildView
var CompositeView = Marionette.CompositeView.extend({
el: 'div#users',
template: '#template',
childView: EmployeeItemView,
childViewContainer: 'table tbody'
});
46
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js CompositeView ChildViewContainer
var CompositeView = Marionette.CompositeView.extend({
el: 'div#users',
template: '#template',
childView: EmployeeItemView,
childViewContainer: 'table tbody'
});
47
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js CompositeView. Data Sort
EmployeesCollection
48
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js CompositeView. Data Sort
Comparator(E1,E2)
EmployeesCollection
49
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js CompositeView. Data Sort
Comparator(E1,E2)
EmployeesCollection
SortModel
50
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js CompositeView. Data Sort
Comparator(E1,E2)
EmployeesCollection
SortModel
CompositeView
51
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js EmployeesCollection Comparator
comparator: function(employee1, employee2) {
//returns -1, 0, 1
}
52
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js CompositeView. DataSort UI
var CompositeView = Marionette.CompositeView.extend({
ui: {
sort: 'span[data-sortBy]'
},
events: {
'click @ui.sort': 'onSortLinkClick'
},
onSortLinkClick: function(e) {
...
}
...
});
53
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js CompositeView. Sort Handler
...
onSortLinkClick: function(e) {
var $el = $(e.currentTarget),
sortBy = this.model.get('sortBy'),
sortOrder = this.model.get('sortOrder');
this.model.set({
sortBy: $el.data('sortby'),
sortOrder: sortBy == $el.data('sortby')
? (-sortOrder || 1) : 1
});
this.collection.sort();
},
...
54
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js CompositeView Initialization
var view = new CompositeView({
el: '#users',
collection: employees,
model: sortModel
});
view.render();
var sortModel = new SortModel({
sortBy: null,
sortOrder: null
});
55
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js Views Communication
<Employee Form />
<Employee List />
EditSave/Cancel
Add
56
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js LayoutView Definition
LayoutView = View * Region
57
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js LayoutView
var LayoutView = Marionette.LayoutView.extend({
template: ...,
ui: ...,
events: ...,
regions: {
employees: '#employees',
employeeForm: '#employee-form'
},
...
createEmployeeFormView: function(model) {
...
}
});
58
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js LayoutView. Region+View
var LayoutView = Marionette.LayoutView.extend({
...
enteremployeeFormMode: function() {
...
this.showChildView('employeeForm',
this.createNewEmployeeView());
}
...
});
59
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js LayoutView. View Events
var LayoutView = Marionette.LayoutView.extend({
template: ...,
ui: ...,
events: ...,
createEmployeeFormView: function(model) {
var view = new EmployeeFormView({
model: model || new EmployeesModel()
});
view.on('cancel', this.onAddCancel.bind(this));
view.on('save', this.onEmployeeSave.bind(this));
return view;
}
});
60
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js LayoutView. View Events
var LayoutView = Marionette.LayoutView.extend({
template: ...,
ui: ...,
events: ...,
createEmployeeFormView: function(model) {
var view = new EmployeeFormView({
model: model || new EmployeesModel()
});
view.on('cancel', this.onAddCancel.bind(this));
view.on('save', this.onEmployeeSave.bind(this));
return view;
}
});
61
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js Conclusions
Marionette.js:
• Offers rich View functionality
• Makes realization of View easier even then in "simple" approach
• Allows to create reusable components
• …
62
Return on Intelligence, Inc. ©2014
All Rights Reserved.
Marionette.js Appendix: One To Many Relation
var employeesView = new OneToManyCompositeView(...);
var notes = new NoteCollection();
var notesView = new OneToManyNotesCompositeView({
collection: notes
});
employeesView.on('childview:show:notes',
function(view) {
notesView.model = view.model;
notesView.render();
notes.url = 'http://.../' + view.model.get('id');
notes.fetch();
});

Introduction to Backbone.js & Marionette.js

  • 1.
    Core Systems TransformationSolutions Backbone & Marionette Tutor: Dmitry Grachikov, ROI
  • 2.
    1 Return on Intelligence,Inc. ©2014 All Rights Reserved. "Simple" Frontend Application var html = "<div>" + "<span>" + data + "</span>" + "</div>"; $('#container').html(html); $('#contaner').append( $('<div></div>').append( $('<span></span>').html(data) ) ); $('span').on('click', function(e) { // do something... $(this).addClass('some-class'); // do something again... });
  • 3.
    2 Return on Intelligence,Inc. ©2014 All Rights Reserved. "Simple" Frontend Application Benefits: • Easy for small amount of code • "Fast" development Drawbaks: • Complexity grows very fast • Hard to understand for medium and large codebase • Specifically to JavaScript: "Callback-Hell" • Hard to maintain • Tight coupling with HTML • …
  • 4.
    3 Return on Intelligence,Inc. ©2014 All Rights Reserved. "Simple" Frontend Application Benefits: • Easy for small amount of code • "Fast" development Drawbaks: • Complexity grows very fast • Hard to understand for medium and large codebase • Specifically to JavaScript: "Callback-Hell" • Hard to maintain • Tight coupling with HTML • …
  • 5.
    4 Return on Intelligence,Inc. ©2014 All Rights Reserved. "Simple" Application Improvements • Assume that "simple" approach with jQuery cannot solve all problems • Separate View from business logic – Solve problem with custom solution – Using effective architectural pattern (for example MVC, MVVM, …) • Create own realization • Use proven framework
  • 6.
    5 Return on Intelligence,Inc. ©2014 All Rights Reserved. "Simple" Application Improvements • Assume that jQuery can't solve all problems • Separate View from business logic – Solve problem with custom solution – Using effective architectural pattern (for example MVC, MVVM, …) • Create own realization • Use proven framework
  • 7.
    6 Return on Intelligence,Inc. ©2014 All Rights Reserved. "Simple" Application Improvements • Assume that jQuery can't solve all problems • Separate View from business logic – Solve problem with custom solution – Using effective architectural pattern (for example MVC, MVVM, …) • Create own realization • Use proven framework
  • 8.
    7 Return on Intelligence,Inc. ©2014 All Rights Reserved. "Simple" Application Improvements • Assume that jQuery can't solve all problems • Separate View from business logic – Solve problem with custom solution – Using effective architectural pattern (for example MVC, MVVM, …) • Create own realization • Use proven framework
  • 9.
    8 Return on Intelligence,Inc. ©2014 All Rights Reserved. "Simple" Application Improvements • Assume that jQuery can't solve all problems • Separate View from business logic – Solve problem with custom solution – Using effective architectural pattern (for example MVC, MVVM, …) • Create own realization • Use proven framework
  • 10.
    9 Return on Intelligence,Inc. ©2014 All Rights Reserved. "Simple" Application Improvements • Assume that jQuery can't solve all problems • Separate View from business logic – Solve problem with custom solution – Using effective architectural pattern (for example MVC, MVVM, …) • Create own realization • Use proven framework
  • 11.
    10 Return on Intelligence,Inc. ©2014 All Rights Reserved. Proven Framework vs Custom Solution Custom Solution Proven Framework + Suitable to the project + No time for learning - Implementation take a long time - After a while can be that new concepts cannot be added + Ready to use + Well documented + Community - Requires time for learning - Can take a time to figure out that framework is not suitable to the project
  • 12.
    11 Return on Intelligence,Inc. ©2014 All Rights Reserved. Backbone.js Marionette.js Models Collections Views ItemView CollectionView CompositeView LayoutView
  • 13.
    12 Return on Intelligence,Inc. ©2014 All Rights Reserved. Backbone.js Backbone.js gives structure to web application
  • 14.
    13 Return on Intelligence,Inc. ©2014 All Rights Reserved. Backbone.js Model Definition var EmployeeModel = Backbone.Model.extend({ defaults: { id: null, name: null, surname: null, dateOfEmployment: null, ... } }); var employee = new EmployeeModel({ name: 'John', surname: 'Johnson', dateOfEmployment: '2000-01-05', ... });
  • 15.
    14 Return on Intelligence,Inc. ©2014 All Rights Reserved. Backbone.js Model Initialization var EmployeeModel = Backbone.Model.extend({ defaults: { id: null, name: null, surname: null, dateOfEmployment: null, ... } }); var employee = new EmployeeModel({ name: 'John', surname: 'Johnson', dateOfEmployment: '2000-01-05', ... });
  • 16.
    15 Return on Intelligence,Inc. ©2014 All Rights Reserved. Backbone.js Model Events employee.on('change', function(model) { console.log('Employee changed'); }); employee.on('change:name', function(model) { console.log('Name changed ' + model.previous('name') + ' -> ' + model.get('name')); }); employee.set('name', 'Peter'); employee.set({ name: 'John', surname: 'Peterson' });
  • 17.
    16 Return on Intelligence,Inc. ©2014 All Rights Reserved. Backbone.js Model Events employee.on('change', function(model) { console.log('Employee changed'); }); employee.on('change:name', function(model) { console.log('Name changed ' + model.previous('name') + ' -> ' + model.get('name')); }); employee.set('name', 'Peter'); employee.set({ name: 'John', surname: 'Peterson' });
  • 18.
    17 Return on Intelligence,Inc. ©2014 All Rights Reserved. Backbone.js Models REST var EmployeeModel = Backbone.Model.extend({ urlRoot: 'http://api.dev/employees', ... }); var employee = new EmployeeModel({ name: 'John', surname: 'Johnson', ... }); employee.save({ ... }); urlRoot 00020000009222iik0
  • 19.
    18 Return on Intelligence,Inc. ©2014 All Rights Reserved. Backbone.js Models REST var EmployeeModel = Backbone.Model.extend({ urlRoot: 'http://api.dev/employee', ... }); var employee = new EmployeeModel({ name: 'John', surname: 'Johnson', ... }); employee.save({ ... }); urlRoot POST /employee Response: { "id": 1, ... }
  • 20.
    19 Return on Intelligence,Inc. ©2014 All Rights Reserved. Backbone.js Models REST employee.fetch(); employee.save({ name: "Some name", ... }); employee.destroy(); GET /employee/1 PUT /employee/1 { "name": "Some name", ... } DELETE /employee/1
  • 21.
    20 Return on Intelligence,Inc. ©2014 All Rights Reserved. Backbone.js Collection Definition var EmployeeCollection = Backbone.Collection.extend({ model: EmployeeModel }); var employees = new EmployeeCollection([ {id: 1, name: 'John', surname: 'Johnson'}, {id: 2, name: 'Peter', surname: 'Peterson'} ]);
  • 22.
    21 Return on Intelligence,Inc. ©2014 All Rights Reserved. Backbone.js Collection Initialization var EmployeeCollection = Backbone.Collection.extend({ model: EmployeeModel }); var employees = new EmployeeCollection([ {id: 1, name: 'John', surname: 'Johnson'}, {id: 2, name: 'Peter', surname: 'Peterson'} ]);
  • 23.
    22 Return on Intelligence,Inc. ©2014 All Rights Reserved. Backbone.js Filling Collection employees.add({id: 1, name: 'John', ...}); or employees.add(employee);
  • 24.
    23 Return on Intelligence,Inc. ©2014 All Rights Reserved. Backbone.js Remove Data From Collection employees.remove(1); //remove by id or employees.remove(employee); //remove by model
  • 25.
    24 Return on Intelligence,Inc. ©2014 All Rights Reserved. Backbone.js Access Collection Data var first = employees.first(); var second = employees.at(1); //Get second element var peter = employees.get(2); //Search by id var john = employees.findWhere({name: 'John'}); var johns = employees.where({name: 'John'});
  • 26.
    25 Return on Intelligence,Inc. ©2014 All Rights Reserved. Backbone.js Collection Events employees.on('add', function(model, collection) { console.log('New employee added'); }); employees.on('remove', function(model, collection) { console.log('Employee removed'); });
  • 27.
    26 Return on Intelligence,Inc. ©2014 All Rights Reserved. Backbone.js Collections REST var Employees = Backbone.Collection.extend({ url: 'http://api.dev/employees', ... }); Define url
  • 28.
    27 Return on Intelligence,Inc. ©2014 All Rights Reserved. Backbone.js Collections REST employees.fetch(); employees.create({ name: "Ivan", name: "Petrov" }); employees.at(0).destroy(); GET /employees POST /employees { "name": "Ivan", ... } DELETE /employees/:id
  • 29.
    28 Return on Intelligence,Inc. ©2014 All Rights Reserved. Backbone.js View Definition Backbone View
  • 30.
    29 Return on Intelligence,Inc. ©2014 All Rights Reserved. Backbone.js View Definition var EmployeeView = Backbone.View.extend({ el: 'table tbody', render: function() { var templateEl = '#template', template = _.template(templateEl.html()), html = template({users: this.collection}); this.$el.html(html); } });
  • 31.
    30 Return on Intelligence,Inc. ©2014 All Rights Reserved. Backbone.js Template <script type="text/template" id="template"> <% users.each(function(user) { %> <tr> <td><%= user.get('id') %></td> <td><%= user.get('name') %></td> <td><%= user.get('surname') %></td> <td><%= user.get('position') %></td> <td><%= user.get('dateOfEmployment') %></td> </tr> <% }) %> </script>
  • 32.
    31 Return on Intelligence,Inc. ©2014 All Rights Reserved. Backbone.js View Render var employees = new EmployeeCollection(...); var view = new EmployeeView({ collection: employees }); view.render();
  • 33.
    32 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js Marionette.Js Marionette simplifies your Backbone application code with robust views and architecture solutions.
  • 34.
    33 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js ItemView Definition var EmployeeItemView = Marionette.ItemView.extend({ el: 'table tbody', template: '#template-user' });
  • 35.
    34 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js ItemView vs Backbone View var EmployeeItemView = Marionette.ItemView.extend({ el: 'table tbody', template: '#template-user' }); var EmployeeView = Backbone.View.extend({ el: 'table tbody', render: function() { var templateEl = '#template', template = _.template(templateEl.html()), html = template({users: this.collection}); this.$el.html(html); } });
  • 36.
    35 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js ItemView Template <script type="text/template" id="template-user"> <tr> <td><%= id %></td> <td><%= name %></td> <td><%= surname %></td> <td><%= position %></td> <td><%= dateOfEmployment %></td> <td> <a href="#" class="promote"> Promote </a> </td> </tr> </script>
  • 37.
    36 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js ItemView. Add UI Element var EmployeeItemView = Marionette.ItemView.extend({ ... ui: { promote: '.promote' }, events: { 'click @ui.promote': 'onPromoteClick' }, modelEvents: { 'change': 'render' }, onPromoteClick: function(e) { e.preventDefault(); this.model.set('position', 'Senior Developer'); } });
  • 38.
    37 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js ItemView. Add Click Handling var EmployeeItemView = Marionette.ItemView.extend({ ... ui: { promote: '.promote' }, events: { 'click @ui.promote': 'onPromoteClick' }, modelEvents: { 'change': 'render' }, onPromoteClick: function(e) { e.preventDefault(); this.model.set('position', 'Senior Developer'); } });
  • 39.
    38 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js ItemView. Add Model Change Render var EmployeeItemView = Marionette.ItemView.extend({ ... ui: { promote: '.promote' }, events: { 'click @ui.promote': 'onPromoteClick' }, modelEvents: { 'change': 'render' }, onPromoteClick: function(e) { e.preventDefault(); this.model.set('position', 'Senior Developer'); } });
  • 40.
    39 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js ItemView Initialization var employee = new EmployeeModel(...); var view = new EmployeeItemView({ model: employee }); view.render();
  • 41.
    40 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js CollectionView Definition var CollectionView = Marionette.CollectionView.extend({ el: 'table tbody', childView: EmployeeItemView });
  • 42.
    41 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js CollectionView Initialization var employees = new EmployeeCollection(); var view = new CollectionView({ collection: employees }); view.render();
  • 43.
    42 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js CompositeView Definition CompositeView = CollectionView + ItemView
  • 44.
    43 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js CompositeView Definition var CompositeView = Marionette.CompositeView.extend({ el: 'div#users', template: '#template', childView: EmployeeItemView, childViewContainer: 'table tbody' });
  • 45.
    44 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js CompositeView Template <script type="text/template" id="template"> <table class="table"> <thead> <tr> <th>Id</th> <th>Name</th> <th>Surname</th> <th>Position</th> <th>Date of employment</th> <th>Action</th> </tr> </thead> <tbody> <!-- Employees will be rendered here --> </tbody> </table> </script>
  • 46.
    45 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js CompositeView ChildView var CompositeView = Marionette.CompositeView.extend({ el: 'div#users', template: '#template', childView: EmployeeItemView, childViewContainer: 'table tbody' });
  • 47.
    46 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js CompositeView ChildViewContainer var CompositeView = Marionette.CompositeView.extend({ el: 'div#users', template: '#template', childView: EmployeeItemView, childViewContainer: 'table tbody' });
  • 48.
    47 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js CompositeView. Data Sort EmployeesCollection
  • 49.
    48 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js CompositeView. Data Sort Comparator(E1,E2) EmployeesCollection
  • 50.
    49 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js CompositeView. Data Sort Comparator(E1,E2) EmployeesCollection SortModel
  • 51.
    50 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js CompositeView. Data Sort Comparator(E1,E2) EmployeesCollection SortModel CompositeView
  • 52.
    51 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js EmployeesCollection Comparator comparator: function(employee1, employee2) { //returns -1, 0, 1 }
  • 53.
    52 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js CompositeView. DataSort UI var CompositeView = Marionette.CompositeView.extend({ ui: { sort: 'span[data-sortBy]' }, events: { 'click @ui.sort': 'onSortLinkClick' }, onSortLinkClick: function(e) { ... } ... });
  • 54.
    53 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js CompositeView. Sort Handler ... onSortLinkClick: function(e) { var $el = $(e.currentTarget), sortBy = this.model.get('sortBy'), sortOrder = this.model.get('sortOrder'); this.model.set({ sortBy: $el.data('sortby'), sortOrder: sortBy == $el.data('sortby') ? (-sortOrder || 1) : 1 }); this.collection.sort(); }, ...
  • 55.
    54 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js CompositeView Initialization var view = new CompositeView({ el: '#users', collection: employees, model: sortModel }); view.render(); var sortModel = new SortModel({ sortBy: null, sortOrder: null });
  • 56.
    55 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js Views Communication <Employee Form /> <Employee List /> EditSave/Cancel Add
  • 57.
    56 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js LayoutView Definition LayoutView = View * Region
  • 58.
    57 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js LayoutView var LayoutView = Marionette.LayoutView.extend({ template: ..., ui: ..., events: ..., regions: { employees: '#employees', employeeForm: '#employee-form' }, ... createEmployeeFormView: function(model) { ... } });
  • 59.
    58 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js LayoutView. Region+View var LayoutView = Marionette.LayoutView.extend({ ... enteremployeeFormMode: function() { ... this.showChildView('employeeForm', this.createNewEmployeeView()); } ... });
  • 60.
    59 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js LayoutView. View Events var LayoutView = Marionette.LayoutView.extend({ template: ..., ui: ..., events: ..., createEmployeeFormView: function(model) { var view = new EmployeeFormView({ model: model || new EmployeesModel() }); view.on('cancel', this.onAddCancel.bind(this)); view.on('save', this.onEmployeeSave.bind(this)); return view; } });
  • 61.
    60 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js LayoutView. View Events var LayoutView = Marionette.LayoutView.extend({ template: ..., ui: ..., events: ..., createEmployeeFormView: function(model) { var view = new EmployeeFormView({ model: model || new EmployeesModel() }); view.on('cancel', this.onAddCancel.bind(this)); view.on('save', this.onEmployeeSave.bind(this)); return view; } });
  • 62.
    61 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js Conclusions Marionette.js: • Offers rich View functionality • Makes realization of View easier even then in "simple" approach • Allows to create reusable components • …
  • 63.
    62 Return on Intelligence,Inc. ©2014 All Rights Reserved. Marionette.js Appendix: One To Many Relation var employeesView = new OneToManyCompositeView(...); var notes = new NoteCollection(); var notesView = new OneToManyNotesCompositeView({ collection: notes }); employeesView.on('childview:show:notes', function(view) { notesView.model = view.model; notesView.render(); notes.url = 'http://.../' + view.model.get('id'); notes.fetch(); });