I have a collection of collections that I feed to my CompositeView.
For each collection I am trying to show a rectangle and inside it show the first 3 models of that collection.
Since there could be more than 3 models per collection I want to trim it down to always be 3 or less. I am using mustache so I can't do it there so I'm thinking of doing it in serializeData for the childView or Show.Item but I'm confused I don't understand the context of serializeData function. When I look at this it gives me the window object.
Where should I do this filtering?
collection 1
collection 1
model 1
model 2
model 3
collection 2
model 1
model 2
model 3
model 4
new Show.Items
collection: collection
class Show.Item extends App.Views.ItemView
template: "templates/_item"
class Show.Items extends App.Views.CompositeView
template: "templates/show"
childView: Show.Item
childViewContainer: '.items'
It seems the context of this is lost, the easiest way to solve this is binding all the methods using underscore's bindall
Related
I have a collection A and a view A
collection A:
model {type: A}
model {type: B}
view A use collection A and all its models.
If I add a new model to collection A, this model is added to view A.
In view B I want to use collection A as well, but not all its models, only models with type B. But I want to use all listeners in View A.
So, If I add a new model with type B in view A, listeners in view B should intercept this and add it to view B.
I can make two different collections, and use two listeners. But this looks dirty.
Is there a way to get get a selection of a collection into a new collection, but keep the same listeners and backbone functions as if it was just a reference to the main collection?
One solution would be to have one collection replicate another (applying a filter at the same time).
From https://jsfiddle.net/t8e6Ldue/
var collectionB = new FilteredCollection(null, {
source: collectionA,
filter: function(model) {
return model.get('type') === 'B';
}
});
see the JSFiddle for full code
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'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.
So I have an object that looks something like this
{
first_name: 'Matt',
last_name: 'Damon',
movies: [{name: 'mov_name1', director: 'Sven'}, {name:'mov_name2', director: 'Joe'}]
}
There is an endpoint that will return this, and I will use fetch to get this data and put it in a model or ItemView. (I have to use fetch because I really want a collection of these objects, so I'll call fetch on the collection.) However, the representation of the object should not be a model alone, it should be a model (or ItemView), and the movies attribute should be a collection, since when I display the row for this object it should be a CompositeView with a model and a collection. My question is how do I convert this object representation to a model and collection after a fetch called on the model?
Sorry it's a bit confusing to explain...
do a fetch on your collection and then for each element create a model and a collection that you can pass then to a compositeView
something like this
mycollection = new MyCollection();
mycollection.fetch();
mycollection.each(function(item){
var actorModel = new ActorModel({firstName : item.get('first_name'),
lastname: item.get('last_name')});
var moviesCollection = new MoviesCollection(item.get('movies'));
var xCompositeView = new XCompositeView({model:xmodel,
collection:moviesCollection});
});
this way your Compositeview gets a model and a collection and you can render them properly using an itemView for each movie.
hope this helps.
If its not a problem to use another framework, there is one called backbone-relational. It is designed to handle the relations between models. See the zoo example in Backbone-Relational
In the example there is a Zoo model and models has a Animal Collection which consist of animal models. With a single fetch on Zoo model, you will have the animal collection as Backbone collection instead of array of plain objects.
I have 2 post collections and a model as follows.
# router file
#posts = new MyApp.Collections.PostsCollection()
#posts.reset options.posts
#followed_posts = new MyApp.Collections.PostsCollection()
#followed_posts.reset options.followed_posts
# Post model file
class MyApp.Models.Post extends Backbone.Model
paramRoot: 'post'
follow_post: ->
# ajax call
console.log "_________Index:#{this.collection.indexOf(this);}"
console.log this.collection
console.log "_________Followed:"
console.log #followed_posts
class MyApp.Collections.PostsCollection extends Backbone.Collection
model: MyApp.Models.Post
url: '/posts_all'
What I am trying to do is when one of the model changed in one collection, I want to update the other model in other collection too.
These collections may or may not hold same models.
So let's say if a model in #posts changed in my Post model, I want to update that model in #followed_posts too. If #followed_posts doesn't have that model, I need to add a duplicate of the model to #followed_posts collection.
I can access the collection that model belongs, but I cannot access the other collection.
Any ideas appreciated, thanks.
If the two collections are antisocial and can't talk directly to each other, which is usually good design, then you'll need an intermediary -- a global event dispatcher. When a model changes, propagate that event to the dispatcher along with a reference to the model. Listen for the event in the other collection and use the model passed to check for existence and respond as needed.
EDIT:
Backbone's documentation mentions this pattern:
For example, to make a handy event dispatcher that can coordinate
events among different areas of your application: var dispatcher =
_.clone(Backbone.Events)
But in fact, this is such a common pattern that the Backbone object itself is extended with Events. So you can just do:
// In your Post model
#on "change", -> Backbone.trigger "post:change", this, #collection
// And then something like this in the collection class definition:
#listenTo Backbone, "post:change", (model, collection) =>
if post = #get model.cid
post.set model.toJSON()
else
#add model
Also, is followed posts a subset of posts? If so, why not put an attribute on the model designating it as followed? Then you could find all followed posts with a simple filter function.
I would strongly suggest that you should consider having a single collection and add some kind of attribute in the model to differentiate between what kind of posts they are.