Using multiple models and collections in Marionette/Backbone view - backbone.js

I'm not sure what the right approach here is. I am setting up a simple form. I need a couple of standard HTML input fields and a couple of select inputs. The data is coming from a couple of different sources and I would like to present the models and collections, with their data to the view like so:
Controller:
var registerView = new registrationView.RegistrationForm({
model: userModel,
model2: departmentCollection
});
myApp.SomeRegion.show(registerView);
Can I do this? Or do I need to split the form into separate regions, all with their own model or collection. If so, how do I call the model data in the template. I have not been able to make it work so far. I cannot find any examples of a form with mixed fields coming from different models and collections,
Many thanks
Wittner

You can do it using a composite view:
var registrationView.RegistrationForm = Marionette.CompositeView({
// ...
});
var my View = new registrationView.RegistrationForm({
model: userModel,
collection: departmentCollection
});
See https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.compositeview.md and https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.collectionview.md (a composite view inherits behavior from a collection view).

Related

Where to place a non-model database fetch architecturally?

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

Backbone JS - Combination of collection, views and models

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.

Trying to add a collection to a model and render it in multiple places in a view

I'm trying to build an app that allows you to create items in a view in multiple places.
For instance, I can add a model from a collection when I create a new model in the parent collection.
The problem I'm having is, when I add the collection to the model and it iterates, it's adding the collection for each loop. So it ends up with LOTS of collections in the model that are repeated.
The parent model render has the following loop:
this.noteTasksViewAdding = new NoteTaskListViewAdding({ collection: tasks });
$('.note-tasks-list-all').append(this.noteTasksViewAdding.render().el);
this.collection.each(function(note){
var view = new NoteView({ model: note });
$('#items-list').prepend(view.render().el);
});
Then the model has the following render in it:
render: function() {
this.noteTasksViewAdding = new NoteTaskListViewAdding({ collection: tasks });
$('.note-tasks-list-all').append(this.noteTasksViewAdding.render().el);
this.$el.html(this.template(this.model.toJSON()));
return this;
}
What I want to have happen is that the collection is added to the model when it's rendered. I'm open to any suggestions on how to do this better.
Thanks!
I faced the problem as well. The solution is to clear the view before you set the collection. In your case, when you set parent view, you might do this:
$('.note-tasks-list-all').html(this.noteTasksViewAdding.render().el);
Then you can append your collection members.

Backbone when to build logic into view vs having separate view

So I know there are many ways for doing things in Backbone, but since I don't have the vast experience of many on here, I would like advice regarding a best approach.
I have a basic CRUD app where I have a form for adding data and a form for editing data, which are essentially the same. And actually are attached to the same DOM element.
So I could include the two forms into one view and serve the appropriate template, depending on whether the view has a model or not. Something like this:
var AddEditView = Backbone.View.extend ({
el: $("#add"),
template: $("editTemplate").html();
render: function() {
if (this.model) {
var theTmp = _.template(this.template)
this.$el.html(theTmp(this.model.toJSON()));
}
else {
var theTmp = _.template($("#addTemplate").html());
this.$el.html(theTmp);
}
},
});
I think this would work however I might run into some sticky issues with any events (i.e. events being bound twice).
Or I could create two completely separate views that would be attached to the same dom element and would toggle back and forth depending on the app state (way more lines of code).
What would you all recommend in this situation. Is more logic in a view better or more lines of code and less logic in views?
Assuming the fields are identical whether you're creating a new model or editing an existing one, I'd recommend having only one view, and only one template. When you instantiate the view, if you are creating a new model, just instantiate a new model and pass it to the view. Otherwise, pass the existing model.
var AddEditView = Backbone.View.extend ({
render: function() {
var theTmp = _.template(this.template)
this.$el.html(theTmp(this.model.toJSON()));
},
someSaveEvent: function() {
this.model.save(); // This will POST if the model isNew() or PUT otherwise
}
});
var model = new Model(); // If you're creating a new model
var addEditView = new AddEditView({
model: model
});

When to use URL attribute for both Collection and Model?

I've been following some Backbone.js tutorials and am a bit confused about when to use 'url' inside Model when there is also a Collection which contains the model. For example I see a lot of code that looks like this, in order to synchronize with the server:
var PostModel = Backbone.Model.extend({});
var PostsModel = Bacbone.Collection.extend({
model: PostModel,
url: "/posts"
});
However I also see some where the model also has 'url' property, like so:
var PostModel = Backbone.Model.extend({
url: "/posts"
});
var PostsModel = Bacbone.Collection.extend({
model: PostModel,
url: "/posts"
});
I think I understand the first method, where I interact with the models only through the collections to which they belong, but I am not sure when you would want to have urls for both a model and its collection.
Sometimes you need a model that doesn't belong to any collection.
For example a login/sign in.
var LoginModel = Backbone.Model.extend({
url: "/login"
});
This way you can interact with login view and model just like you would with any other Backbone model, including save() (which posts the login form to the server) and validation.
There is however no login collection, so it doesn't make sense to model that.
Maybe the code you're seeing is something in between. Models are accessed via collection in some places of the application and without collection in others.
If it's a good design is another story, but there's no technical reason to not do it.
edit
As you noticed, using urlRoot is another option, since by default the url attribute is a method that uses urlRoot to construct the relative url.
It can be, however, given a string value to specify the model url directly.

Resources