Deleting a collection when closing a CollectionView in Backbone.Marionette - marionette

After closing a CollectionView in my project, the collection it makes reference to is still available. Opening again the CollectionView duplicates the collection as it reloads the data again. I think this is expected behaviour as in the documentation it says that all the CollectionView does on close is:
unbind all listenTo events
unbind all custom view events
unbind all DOM events
unbind all item views that were rendered
remove this.el from the DOM
call an onClose event on the view, if one is provided
I'm guessing it's on me to manage the collection on the onClose event handler. Is there a good way of deleting the collection and models associated with the view?

In your situation it's not necessary to delete the collection. Variables (in this case your collection) that are not directly referenced by another object will be garbage collected by javascript. So when the view and module close and nothing else is referencing the collection it will be removed.
If you want to make absolutely sure you won't get any zombie events you can clear it's event listeners when you close the module and/or view:
myCollection.off();
Of course is your collection is a global variable (technically a property of the window object) then yes it might be a good idea to delete it like so:
delete window.myCollection;
Aside from this, removing it from memory is not something you need to worry about as the other objects referencing are closed...

Related

Titanium: correctly clean up a controller associated with a non-window view

I have an Alloy app structured with a one window divided in two views: a sidebar menu view on the left and a main view on the right.
Each time the user click on a different menu-item in the sidebar I remove all children attached to the main view and load the view/controller related to that menu-item and attach it to the main view. My question: is this sufficient? If the removed view had event listeners attached to elements inside it, are they clean up too or not?
Have I to keep a reference to each controller I have instantiated and call controller.destroy() and controller.off() before I load the new view/controller or is not necessary?
I am asking because with views without window is not possible to attach a cleanup function to the "onclose" event because the UI.View elements can't be "closed" (only windows).
So which is the correct way to handle this situation in Titanium?
The event listeners may keep a reference especially you add them with Ti.APP.addEventListeners.
So, you should remove event listeners manually when you remove all children view.

Moving an ItemView from one CollectionView in another without deleting it, best practice?

I'm building a dashboard builder and view interface with Marionette. I have some views from legacy code that are pretty heavyweight(large reports) and the html is thus pre-constructed on the server.
I have a Marionette CollectionView for each row in the dashboard which contains an ItemView for each widget that was dragged onto the row during dashboard building.
When the user moves a widget from one row to another I want to avoid deleting the view and having to reconstruct it (because it would be a lot of unnecessary dom manipulation) but instead want to just detach the element from one(row) CollectionView and add it to another. What's the best practice for accomplishing this with CollectionViews in Marionette?
It seems by default moving a item across CollectionViews would destroy the view/model from one and re-instantiate/re-render it in the other.
The concern I have is that the tablereport in the DOM that would be moving from one collection to another is not original Marionette/Backbone template generated View, it would be just a predefined DOM element we set as the view's el.
The tablereport DOM element has lots of children elements with events associated with it via legacy code not the Backbone view events array nor via Backbone's listenTo calls. So destroying the DOM tablereport element is what we need to avoid to preserve those events, we just want to relocate it in the DOM.
Whats the best way to handle this functionality efficiently in Marionette.
A couple options spring to mind, but the fact that your event-binding code is not easily callable means you'll probably want to use the jQuery detach() method to keep all your events bound when you remove an element.
One option is to cache your view elements as you build them:
- write a view factory which you delegate to in the buildItemView method of your CompositeView.
- have your factory cache the elements for the views it creates against the model.cid of the model that is passed in as the first parameter to the buildItemView method.
- when your factory method is called, retrieve the element from the cache if it exists, call detach() on it, and set it as the ItemView's element.
- override the render method on the view to stop it from rebuilding the html
- move the model from one CollectionView's collection and put it into the other CollectionView's collection, and Marionette will then build your view as described above and insert the element (with events still bound) into the DOM.
Instead of doing the above, you could, assuming you know which ItemView has been dropped:
- remove the ItemView from the first CollectionView's children container (this is a Backbone.Babysitter instance, I believe, and there is documentation for it)
- detach the ItemView's element
- insert the ItemView's element into its new place in the DOM
- insert the ItemView into the second CollectionView's children container
- remove the model from the first CollectionView's collection
- add the model into the second CollectionView's collection silently, which prevents the CollectionView from triggering its normal behaviour of building a new view, rendering it and inserting it.
The first way is probably more elegant as you are still letting Marionette do its thing, but just altering the building, rendering and inserting of the ItemViews. The second way is less complex, but means you have to manually keep everything in sync yourself - essentially doing what Marionette would normally do behind the scenes and stopping it from 'interfering', so to speak.

When using data binding, how do I know when a control was added?

When using data binding, how do I know when a control was added?
I'm using ItemsControl element with ItemTemplate.
I want to know when a control was added like event(ex. OnControlAdded)
Please help me
That's not how it's supposed to work, you got it upside down.
You're supposed to have a ViewModel, and Collection in there that you then bind to your ItemsControl.
On that collection, which should be observable, you have a CollectionChanged event. Subscribe to this one, it will fire when elements are added/removed which in turn will make your ItemsControl grow/shrink.

Unify ViewModel through-out UserControl

I'd like to know how to set a single ViewModel throughout a single UserControl. I'm using an Items container inside a user control (bound to ItemsSource) and it doesn't seem to update with the code-behind replacement of a DataContext (to a code-behind instantiated ViewModel)
What i'm trying to do is change the DataBound foreground color of every text Item in the userControl, and the items inside an Itemscontrol dont seem to change. forcing a datacontext change removed the collection items from display.
I think I'm conceptually Misunderstood here. could anyone help?
I could fix the problem by using Storyboards to change color but the problem was still the same. The eventual solution was to access the resources inside the templates, which is possible by browsing the Visual Tree as shown in this tutorial
http://windowsphonegeek.com/tips/how-to-access-a-control-placed-inside-listbox-itemtemplate-in-wp7
The peculiar thing though, was that I needed to look for my object inside the initial object returned, as it seems to return the System generated one, which you don't see yourself. Looking for the answer inside this one helped. Also, pushing them into a list of items for easy access later could be a general idea, but MS needs to fix the way of doing this pronto.
I would recommend binding the ItemsSource to a property in your ViewModel.

Disappearing NSManagedObjects

I am working on a document based application.
When opening up a saved file, I load in the NSManagedObjectContext to a view controller. This view controller needs to observe changed on the property "depth" on all objects of a certain type. When the view controller gets the context, it gets all these objects, adds itself as an observer of that value on each, and keeps them in an array to keep track.
Whenever Core Data sends the ContextDidChange notification, I add created objects to this array after observing them. For the deleted objects, I remove the view controller as an observer and remove them from that array.
This works great until I close a document and reopen it. When this happens, all the objects are added to this array. The observation works fine. However, the second the first "NSManagedObjectContextObjectsDidChangeNotification" comes in, all of my NSManagedObjects are somehow no longer in the array I set up. On delete, I get a crash telling me I can't remove an observer that's not an observer.
It's very strange.
Why are those NSManagedObjets suddenly gone? I don't release the array or do any funny business with it at all.
When you close a document and reopen it, you are getting a new view controller object.
However, it sounds like the original view controller is still around and still observing:
NSManagedObjectContextObjectsDidChangeNotification.
Check to make sure that when you close your document that the view controller is removing itself as a notification observer.

Resources