I have an application that does CRUD for a Collection of Models. There is a DisplayView for each model that is always visible. There is also an EditView that is visible only when the associated DisplayView is clicked on.
The DisplayView and EditView appear inside of different parent views. Right now I am using the "event aggregator" pattern to tell my application to render the EditView when a DisplayView is clicked. Pattern described here: http://lostechies.com/derickbailey/2011/07/19/references-routing-and-the-event-aggregator-coordinating-views-in-backbone-js/
When one of my DisplayView is clicked it fires an event that the parent of the EditViews listens to. When it receives this event it renders the appropriate EditView, based on the model for which the event was fired.
This works well for most of my application, but is particularly cumbersome when I want to have the EditView change position based on the absolute position of the related DisplayView in my application. Rather than have the DisplayView directly control the position of the EditView, it triggers a "please reposition yourself to these coordinates" event. Such direct communication doesn't feel like something that should be broadcast to the entire application. I'm starting to wonder if for my case I should just have a reference to the appropriate EditView as a property of each DisplayView rather than decoupling them.
The problem, as I said, is that they are rendered inside of different parent views. The DisplayViews get rendered in the HeaderView while the the EditViews get rendered in the ContentView.
How do others handle situations like this? The EditView in some ways belongs to the DisplayView, but that does not match the way my application's DOM is structured. Assuming I do create a direct link between each EditView and DisplayView, how would I handle show/hide of the EditView? Would the DisplayView also need a reference to the ContentView container, which it would render explicitly with the appropriate EditView as a parameter?
As much as you can, definitely avoid views holding references to parallel views (as oppose to parent / child views) and modifying each other, this can quickly turn into spaghetti and make your code much more fragile. Instead, the following patterns allow your different views to stay decoupled while still get the job done.
Global Notifications / events
This is the one you mentioned. It works but like you mentioned is less than elegant because it broadcast itself in the global scope unnecessarily
Binding / Observer Pattern
make an object named
editViewPositionin your controller and expose methods to let the display view change the values of the editViewPosition. TheEditViewcould then listen for and observe changes in theeditViewPositionand update itself accordingly. The strength of this approach is that later you can have 5 differentEditViewsall observing the same propertyeditViewPositionon your controller and update themselves accordingly, and there would be nothing you need to change in yourDisplayViewfor that to happen.Delegate pattern
Instead of directly hooking up the views and calling methods on each other, you can allow the display view to have a
delegateproperty, which can be set by the controller to be theeditview. When theDisplayViewwants its edit view updated, it will check if its delegate exists and implements a predefined function, if so, it will call the function. This approach is more coupled than the observer pattern but still allows a high degree of decoupling (and later for instance you can swap an entirely different view in there instead of your edit view and the program should still work.) Weakness of this approach is that you typically only have a single delegate, but it is more direct than any of the other patterns mentioned.Manually maintaining a list of objects to notify
This is almost an extension to the delegate pattern. Basically you have an array of
EditViewlike objects in your display view, and whenever needed, your display view will go through the array and call method on each of those objects. This array would again be populated by your controller.Conclusion
Personally, I'd most likely use the binding and observer pattern for your use case. In general, views that are parallel (no direct parent / child relationship) should not hold references to each other and should only communicate via a common controller / event / notification / other super-structure that they share.