Backbone JS where to put Application main logic - model-view-controller

Using Backbone i'm starting to build an App where i have everything cleanly separated. But now i have the following question. Where should i put the App main logic, in the views or in the model.
For example i have a view and a model, which are binded to a button and when i click that button i have to make
$.ajax(params)
do i put that in the view or the view calls a method with :
this.model.doAction(params)
which do you think is the best approach?

You can define an events property in the view which is of the format {"event selector": "callback"} for eg. {"click .collapse": "collapse"} where collapse would be a function defined as a property of the view. Then write your ajax request code in this callback function.
Also, unless I am missing something, "binding a view and model to a button" doesn't sound correct Backbone way to me. Instead you should think of one instance of model associated with one instance of the view. Whenever an attribute of the the model instance changes, a model change event will be triggered. You can bind a view function to this event so that change in the model is reflected in the view. Here is a quick example
var Book = Backbone.Model.extend({
// ...
});
var BookView = Backbone.View.extend({
initialize: function () {
this.model.bind('change', this.render, this);
},
render: function () {
// here, make changes to the dom as per changes in model
}
});
To associate a model with a view instance, you can pass the it while instantiating a new
view object..
var book = new Book({
title: "A great book"
});
var view = new BookView({model: book});
view.model.set('author', 'AGreatAuthor');
The set function call will fire change event and will result in render function of view
to be called.
Refer to the annotated source of Todos app example for a complete example.

Related

Backbone routing and view relations

I'm preparing to build a medium sized website with Backbone for the first time. There are 7 menu items, and I cant figure out whats the best routing/view relationship when it comes to performance. When a route is triggered, do I create a new instance of the "active" view every time it's triggered or do I only create one view instance for each view, when the user loads the page?
... And whats the best way to handle views – adding and removing dom elements and events, without having trouble with performance. e.g.
$('selector').html(my-new-view);
You can create your menu only once, if it doesnt change. You can create some html template like this.
<div>
<nav>render-here-only-one</nav>
<section>render-here-when-page-changes/loads</section>
</div>
I prefer backbone's render method initialize and append itself.
var testView = Backbone.View.extend({
el: $("#section"),
template:_.template("<strong>hello.</strong>")
initialize: function () {
// any change on view will trigger render
_.bindAll(this, "render");
},
render: function (item) {
this.el.html(this.template());
}
});
var myView = new testView();
myView.render();

An aesthetic or correct way of invoking an action that requires DOM manipulation as well as controller related tasks in EmberJS

My EmberJS app has a couple of actions (triggered by buttons) that require a view/DOM manipulation as well as setting a state in the controller, followed by a model update. The way I do this, it does not appeal to my programming aesthetics. It gets the job done, but it doesn't look good :(
Here is a gist of how I do things :
<button {{action 'whatever' target='view'}}></button>
App.MyView = Ember.View.extend({
actions:{
whatever:function(){
var ctrl = this.get('controller');
ctrl.set('property',value); // arbitrary example of setting a controller property through it's view
ctrl.controllerMethod(); // invoking a controller method through the view
**// do some DOM manipulation**
}
}
});
Naturally, I can wrap whatever controller related steps I am performing in the view in a controller method and invoke that method through the view, but IMO that's just equally ugly. The view shouldn't really be invoking a controller method like how I have done. Unfortunately, this specific action requires a DOM manipulation as well as setting some state and performing an action in the controller.
I am not sure what is the recommended way of performing this. Can anyone enlighten ?
I suggest you handle the action from the controller. I noticed you're setting a property. You can use that to signal something to the view and then do the DOM manipulation within the view.
App.MyView = Ember.View.extend({
function () {
**// do some DOM manipulation**
}.observe('controller.property');
});
The way I think about it is that UI 'actions' are mapped to a business event (e.g. addClient instead of click), then as a result of that something happens that could change properties of the model, controller. As a result of those changes the view might need to update directly, ideally through a binding, but sometimes is needed to modify the DOM manually.
as #LukeMelia said in his comment you should really handle the changes in your controller and update your view (if you need to?) via databinding.
so, you would just omitt the target="view" argument from your view helper and Ember will look for the proper action in the nearest controller, bubbling all the way up to the route, and so on.
a simple code snippet (with what you provided in your first post) would look like:
Handlebars Template:
<button {{action someAction}}>Fire!</button>
Ember.Controller:
App.MyController = Ember.ObjectController.extend({
myProperty: 'cool',
printMyCoolness: function () {
console.log("I'm using Ember.js!");
},
actions: {
someAction: function () {
this.set('myProperty', 'set on fire!');
this.printMyCoolness();
}
}
});

KendoUI : Confused about when bindings actually 'fire'

Using Kendo UI's MVVM framework, I am getting confused about how bindings that are wired in javascript actually work. Given a view model, I have tried the following;
var viewModel = new kendo.observable({
Items: [],
onUpdateItems: function(e){
console.log('updating items');
}
});
viewModel.Items.bind('change', function(e){
viewModel.onUpdateItems(e);
});
viewModel.trigger("change", { field: "Items" });
This does not cause the function to trigger. Though if I actually change items in the view, like interacting with it, it causes the function to fire. This doesn't make a lot of sense to me.
You're binding the change event for viewModel.Items, so you need to trigger the event there. If you change your call to
viewModel.Items.trigger("change");
it will call viewModel.onUpdateItems().
Change events will bubble upwards (from an inner ObservableArray to the outer ViewModel, for example), but not the other way. So if you trigger the change event for the view model, it will not fire the event for the nested ObservableArray Items.

does an onclick function go in model, view or controller?

I am using backbone.js and trying to stay strict to the model-view-controller structure as I learn it. I have an onclick function for a link in one of my views that I am not sure where to put. Is the best place to keep this in the render function of the view?
Thanks
More specifically, the onclick performs a facebook login and then adds the user to my database if they are not currently in it. Don't know if this changes anything.
Here is what I think I will go with:
var NewUserView = Backbone.View.extend({
el: $('#window'),
render: function(){
// Render
this.listeners();
},
listeners: function(){
// onclick and other listeners
}
});
From the Backbone documentation:
In Backbone, the View class can also be thought of as a kind of
controller, dispatching events that originate from the UI, with the
HTML template serving as the true view. We call it a View because it
represents a logical chunk of UI, responsible for the contents of a
single DOM element.
Here's the general way to handle events in Backbone:
var NewUserView = Backbone.View.extend({
el: $('#window'),
render: function() {
// Render
},
events: {
"click #facebookButton": "loginViaFacebook"
},
loginViaFacebook: {
// Perform facebook login and add user to database
}
});
Where do you want the link to appear? On View page right? So , you should keep it in the same view on which you want the link to appear.
But , if you are building an architecture rather than just a web application, then you should put the onclick function in some different file where you will keep all these function and then import them in the view as required or keeping them in separate files and bundling them for import on view page.
Please make a file and write all the functions in that file and include that file in the your view file and use the onClick in the anchor tag. Please let me know if this make sense.

Backbone.js - Binding from one view to another?

I have a main app view, with a filter menu in the header. When it's clicked, I want to filter content in a seperate news-feed view. But I don't know how to bind events (and pass class data) from clicks in one view to a function in another.
How can I accomplish this?
There are a number of ways to accomplish this, but probably you want to create a model object, which is shared between the two views. Then on 'click' in view one, update the model object, and bind 'on change' in view two to the model object.
Basically, you can set up both views to stay in sync with the model object, and any changes to the object will result in changes to the view.
Everything in Backbone inherits from Backbone.Events, so you can trigger and bind events from anywhere (docs for Backbone.Events):
var View1 = Backbone.View.extend();
var View2 = Backbone.View.extend({
eventHandler: function(data) {alert(data)}
});
var v1 = new View1;
var v2 = new View2;
v1.bind('hello-world-event', v2.eventHandler)
v1.trigger('hello-world-event', 'Hello World!')
Note that in this example, when v2.eventHandler is called, 'this' will refer to v1. See the backbone docs for more.

Resources