I have a nested composite view that checks its model for a collection, and if so sets that collection to itself as its collection.
onRender: ->
if model.attributes.has_collection
#collection = model.get 'myCollection'
This works quite well when the model has a collection, and the item view(s) all display, and when I add a new model to the collection, a new view appears.
However when there is no collection, and the button is clicked to create a new model, I need to create the model, set the collection (a collection of one) to the view's model, and get the view to display the model and any further models that are added. I have tried various things, right now I set the collection on the model and then run this function :
class List.myCompositeView
childView: myView
// *** //
setChildren: ->
#collection = #model.get 'myCollection'
#render()
The first model appears as it should, but further models that are created do not display. To repeat, they do appear when the collection is set in the onRender function. I realize there is lots of code that I did not add here, so if there is something (potentially) relevant to the problem that you need to know, let me know. Could it be that the view is not binding to the collection's events properly? Thanks!
A marionette collectionView has a private method called _initialEvents. When your collectionView is constructed it sets up this method to be called the first time the view is rendered. If your first render is when a collection view is not set then this would make sense that the events would not get wired up correctly. You should be able to call this private method after you set the collection and everything should work: #_initialEvents()
If it is helpful, this is the implementation of that method:
if (#collection) {
#listenTo(this.collection, 'add', #_onCollectionAdd);
#listenTo(this.collection, 'remove', #_onCollectionRemove);
#listenTo(this.collection, 'reset', #render);
if (#getOption('sort')) {
#listenTo(#collection, 'sort', #_sortViews);
}
}
Related
According to the documentation, you have to implement INotifyCollectionChanged on the source collection of a ListCollectionView to propagate adding/removing of collections items.
So I don't understand how his is working:
var parent = new Parent();
parent.Childs = new List<Child>();
parent.Childs.Add(new Child());
parent.Childs.Add(new Child());
parent.Childs.Add(new Child());
var view = new ListCollectionView(parent.Childs);
Assert.AreEqual(3, parent.Childs.Count);
Assert.AreEqual(3, view.Count);
parent.Childs.Add(new Child());
Assert.AreEqual(4, parent.Childs.Count);
Assert.AreEqual(4, view.Count);
Please, can anybody explain how this is working?
Why wouldn't this work? You are asserting after you have added the Child items. The Count property will always return the corrent number of items.
The reason why you need to implement the INotifyCollectionChanged interface is for a view to be able to know when it should refresh the UI.
For example, if you add an item to a data-bound collection that you are displaying in a ListView, the source collection needs to raise the CollectionChanged event for the new item to automatically show up in the view.
We have written a base Backbone view class which abstracts the common methods and properties. All our view class in a module extends this base class. Also this classes use same model.
The model contains a collection. I am listening to change event of collection. Whenever there change in collection i want to listen for change event to the corresponding view. Instead this event is getting triggered for all the model instances created.
Please share your inputs to resolve this issue.
in your base view, you can listen to model change events like this
intialize: function(options){
....... init code
this.model.on('change',this.modelChanged, this);
}
then in the modelChanged handler you can trigger a custom event on the view
modelChanged: function(){
this.trigger('modelChanged', [your args]);
}
then you can listen to the custom view event with 'on' function like we did with the model
Looking at some backbonejs examples on codeschoo.com, I don't see any explicit associations between views and their models. How does a view know what model it should be associated with? Is it by convention, e.g. TodoView assumes that this.model is of type Todo?
To explicitly set the model to the view, is it just a matter of passing in the model in the constructor?
If you pass a model property to a view constructor, it will set that directly as a property of the view instance, e.g. view.model. That's the case for a select group of other properties as well. Beyond those, properties passed to view constructors are set in view.options.
So yes, you can do this:
var view = new Backbone.View( {
model : new Backbone.Model
} );
Or change a an existing view instance's model any time by assigning to model:
view.model = new Backbone.Model;
Some people set references to views in models (e.g. model.view), but so far I've avoided that.
http://backbonejs.org/#View-constructor
When creating a new View, the options you pass are attached to the view as this.options...There are several special options that, if passed, will be attached directly to the view: model, collection, el, id, className, tagName and attributes.
I'm using ObservableCollection<T> to bind some data to some view.
While I'm editing DB existing data, I can save data edits by calling only a single Savechanges() method in my view model, also add new items to collection and I can edit them, but the SaveChanges() method doesn't insert additional rows to db.
I don't know what entities are passed to the viewmodel. The T is a merged class of multiple entities so I have to do this.
In Constructor:
collection=globalContext.TSet;
//the collection and context are defined in class level
Code to get a new item:
collection.Add(New T());
CurrentItem=collection.Last();
where collection is the ObservableCollection<T> and CurrentItem is the currently editing item.
EDIT:
The context.ChangeTracker.Entries doesn't recognise the new object.
I have a complex type(say T) which is the result of some join query,I have no idea that T is creating from which entities so I can not get the Entity => I can not say the context that what type of Entity I want to add.
So I have to force change tracker to create the new object from complex type which is the result of some join query.
I'm using EF4.3.1
Any suggestions?
Thank you.
The database is not getting updated. Modify the DBSets in the view (or view model) via IDbSet, then issue a DbContext.SaveChanges Do this instead of directly modifying the ObservableCollection. The ObservableCollection should then refresh itself and update the view model and view. If it does not requery the database to generate a new DbSet then get a new ObservableCollection from DbSet.Local for the view model then create a new view from that.
You haven't added the new entity to TSet. You need to call TSet.Add(t) or hook up the CollectionChanged event of the ObservableCollection to do it automatically.
We have multiple filters based on the same collection. i.e. we are displaying the same collection in a variety of ways. What i would like to be able to do is ask all of the CollectionViews to refresh when a property changes (as the collection view will only refilter if items get added/removed from the collection). Is there a way to find all the collectionViews associated with a given collection. Is there a two way link between the collection view and the collection, or a way to determine this link.
P.S. I dont think the answer is
ICollectionView coll = CollectionViewSource.GetDefaultView(Collection);
as this will give me the default view for the collection, not all of the ICollectionViews asscoiated with the Collection.
If your collection is an ObservableCollection, you can do a ResettableObservableCollection.
public class ResettableObservablecollection<T>: ObservableCollection<T>
{
//copy desired ctors
public void ForceReset()
{
OnCollectionChanged(new System.Collections.Specialized.NotifyCollectionChangedEventArgs(System.Collections.Specialized.NotifyCollectionChangedAction.Reset));
}
}
The ICollectionView that gets generated will be watching for that and refresh itself.