I've the following backbone model.
var Credential = Backbone.Model.extend({
defaults: {
user: null,
password: null
}
});
I want to bind this model to a view.
Is it a best practice to instantiate the Credential model from the router and pass to the view
var loginView = new LoginView({ model: new Credential() });
or instantiate the model in the initialize method of the LoginView.
var LoginView = Backbone.View.extend({
initialize: function() {
this.model = new Credential();
}
});
The best practice is to assign a model to the view, an not let the view create the model.
Conceptually, a view is one representation of a model, when you can have multiple views representing the same model (for instance a form, and a list).
This is why keeping them loosely coupled and assigning a model to a view is usually a better pattern.
There is also one way you can follow. As you may know, backbone view share Controller task from MVC. So you may detach Controller responsibility from view in a independent abstraction, like it made in Marionette.js framework. It this case you will have workflow as following:
1) Controller is in charge of creating and delete views and models, models fetch, providing models to views.
2) Views listen to model events, DOM events and render actual model data
3) Model is only in charge of working with data
Related
I am developing a rich client application using Backbone.js and have encountered a situation where I need to fetch 3 values from three database tables and display them.
The rub, however, is that they are not part of my models and I have no need to synchronize them. They are for display purposes only. Should I created a child view which adds them to the DOM as part of the render() method? I'd prefer not to just hack some jQuery code together -but- it doesn't seem to fit nicely into my mental picture of Backbone models and views either.
The rule of thumb in MVCs like Backbone is that the data structure should always be stored in the model layer imo. In your case this could either mean extending your current models with those ui state related attributes (recommended) or create a new model and pass it to the views as an option:
var myModel = new MyModel();
var newModel = new NewModel();
var myView = new View({
model: myModel,
newModel: newModel
});
later in the view you can access to the newModel as this.options.newModel
I had the following setup now in three different projects, so I thought maybe it's worth asking here. There's a chance I'm not the only person wondering about this.
So there it comes:
I have a list of objects
The list items have a special function like draggable or onClick-Events
My question: How do I build this scenario with Backbone?
I guess I create a model and a view for my list objects. I use a collection for keeping together my objects.
Now I wonder: Do I instantiate the object view in the model constructor and instantiate the models in the collection constructor? Or is there a better way to achieve what I want?
Neither; use a mediator to instantiate the views and inject them with their model/collection.
Marionette.js has a nice implementation for this sort of mediating object, called Controller - I suggest you check it out.
Further more, you don't have to explicitly instantiate the collection models - just declare their type in the collection's prototype, e.g.:
var MyModel = Backbone.Model.extend({
// do some shit
});
var MyCollection = Backbone.Collection.extend({
model: MyModel // pass the type for the collection to instantiate
});
Taking our mediator/controller approach further, this is how it could be done (with Marionette.js):
var MyController = Marionette.Controller.extend({
initialize: function () {
this.myCollection = new MyCollection();
this.myCollectionView = new MyCollectionView({
collection: this.myCollection
});
}
});
This, of course, is just a skeleton code, meant to roughly demonstrate the MVC approach, but it's a good starting point.
I try to write two views login view and register view each renders with same data which is collected from a keyup dom event in both views. Login template has less data field, so less template variables, than register template does.
So I thought of using one model for gui render of those two, forms data model. I am trying to separate the concerns and keep single responsibility for my modules. Now, it is needed to make forms data model a dependency of one view and create in this view, and mention this same instance from the other by making the former view a dependency of this other view. Yet this last should use the same instance of the view it has as a dependency. It seems having only one view and three separate models forms data, login and register and two different templates can be a solution.
This seems surprising. In object orientated paradigm it feels adding a little feature makes its very fast cumbersome, which conflicts with the object orientation ideas. All this feature is for when user clicks register button in the login view the register view render with the just entered data and vice versa.
Is that usage, referencing one view/model from another one for using its models etc., is a wrong use of the Backbone or Require while they are meant to utilise good developing practices such as separation of concerns, single responsibility, and modularisation separation, or that is not bad at all regarding those good dev practices?
I don't think it's "wrong" per say to have View1 depend on View2 so that View1 can access a Model that View2 creates ... but I do think it's sub-optimal. I can think of two other strategies you might want to consider that would let you avoid making View1 depend on View2.
First, you could opt not to create the Model in View2, and instead just populate it in View2 ... and create it beforehand in its own module. In other words:
// theLoginData.js
define(['LoginData'], function(LoginData) {
return new LoginData();
});
// View #2
define(['theLoginData'], function(theLoginData) {
return Backbone.View.extend({
someMethod: function() {
theLoginData.set(whatever);
}
});
});
// View #1
define(['theLoginData'], function(theLoginData) {
return Backbone.View.extend({
someOtherMethod: function() {
var whatever = theLoginData.get('whatever');
}
});
});
The other option would be to still create the Model in View2, but "register" it at a more global scope (eg. as a static property on the Model class you use for your login data Model):
// LoginData.js (ie. the Model class for your login data)
define([], function() {
return Backbone.Model.extend({}, {
currentLoginData: null
});
});
// View #2
define(['LoginData'], function(LoginData) {
return Backbone.View.extend({
someMethod: function() {
LoginData.currentLoginData = new LoginData(whatever);
}
});
});
// View #1
define(['LoginData'], function(LoginData) {
return Backbone.View.extend({
someOtherMethod: function() {
var whatever = LoginData.currentLoginData.get('whatever');
}
});
});
What is the best way to remove a model from a collection that has been removed in the DOM. Let me ask a better question, how do I keep views in sync with a collection?
remove the view first, while removing execute
this.model.collection.remove(this.model);
you can check with conditions to whether current view has a model, and that model has a collection etc before you execute the same.
I've followed the backbone Todos example application. This keeps view state up to date with collection.
Pass models to any view created like so:
var someView = new SomeItemView({ model: modelFromCollection });
Then listen to events on that model and react from the view:
initialize: function() {
this.listenTo(this.model, 'destroy', this.remove);
// listen to other events ...
}
I am new to Backbone.js and I have the following problem: I have multiple views that uses the same model. I do not want to re-fetch model on every view render, but I want to fetch it only once and then when view is rendered use that instance/data.
My example: I have 3 views for user. One is some user statistics, another user info and third user profile. After login user lands on user profile view and there I fetch the user model but how could I then pass this model reference around or even better how could I access that model data from different views?
I hope I am not doing any anti-pattern here. I have seen a lot of examples with binding events to model change and then rerender all the views but that is not my case. I am using backbone.js with require.js and underscore template engine.
Just return the instantiated model:
define(function (require) {
var MyModel = Backbone.Model.extend({})
return new MyModel()
});