Skip to content

Instantly share code, notes, and snippets.

@syedahmedhussaini
Created May 3, 2013 19:40
Show Gist options
  • Save syedahmedhussaini/5513282 to your computer and use it in GitHub Desktop.
Save syedahmedhussaini/5513282 to your computer and use it in GitHub Desktop.
Supervising Presenters
//------------------------------------------
//- Model ----------------------------------
// The model is abstract and has no knowledge of the presentation layer.
var Product = Backbone.Model.extend({
initialize: function(){
this.set({price : 0, pricePlusTax : 0});
this.on("change:price", function(){
this.set({pricePlusTax: this.get('price') * 1.2})
})
}
});
//------------------------------------------
//- Use Case Service -----------------------
// This service is responsible for coordinating the use case execution.
// It can run validations, check some high-level policies, and persist the model.
var UpdatingProducts = {
update: function(product, listener){
//.....
//some work
//.....
listener.successfulProductUpdate(product)
}
};
//------------------------------------------
//- Some Other UI Component ----------------
var ConfirmationDialog = {
confirm: function(message, data){
//....
}
};
//------------------------------------------
//- View -----------------------------------
var ProductUpdateForm = Backbone.View.extend({
//Transforms a low-level DOM event into a high-level screen event.
events: {
"click button[name='save']": function(){this.trigger('save');}
},
//Notice, everything here is declarative.
bindings: {
"input[name='price']" : "price",
"input[name='price-plus-tax']" : "pricePlusTax"
},
render: function(){
this.$el.html(productFormTemplate(this.model.toJSON()));
this.stickit();
return this;
}
});
//------------------------------------------
//- Presenter ------------------------------
var ProductUpdatePresenter = Backbone.Marionette.Controller.extend({
initialize: function(opts){
// All the dependencies are injected and, therefore, can be mocked up.
this.product = opts.product;
this.updatingProducts = opts.updatingProducts; // use case service
this.productUpdateForm = opts.productUpdateForm;
this.confirmationDialog = opts.confirmationDialog;
this.listenTo(this.productUpdateForm, 'save', this.updateProduct, this);
},
updateProduct: function(){
// Implements non-trivial UI interactions, such as confirmation
if(this.confirmationDialog.confirm("Please review the data", this.product)){
// Does not contain any domain logic. Delegates to the use case service instead.
// Notice that we are passing the presenter into the use case service.
// The service will notify the presenter about the results of the use case execution.
// The presenter can react (for instance, close some sort of dialog).
this.updatingProducts.update(this.product, this);
}
},
// This method will be called by the use case service
successfulProductUpdate: function(product){
//....
}
});
// Setting everything up
$(function(){
var el = $("#content");
var model = new Product();
var form = new ProductUpdateForm({el: el, model: model});
form.render();
new ProductUpdatePresenter({
product: model,
updatingProducts: UpdatingProducts,
productUpdateForm: form,
confirmationDialog: ConfirmationDialog})
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment