How to make an action affect a sibling view without controller.get('view')?
Asked Answered
C

1

6

Quick context: Application view has 2 outlets. One for a toolbar. The other for the routable "main" view hierarchy.

app -- main
   \-- toolbar

I need some buttons in the toolbar to trigger events in the "main" view. Not update any data in any model. I simply instruct it to trigger some changes to a drawing library that the view is presenting. Clearing the canvas, resetting zoom value and such.

In 1.0 pre2 and earlier I have used actions and router.get('someController.view') to get access to the view I want and trigger the action/method/event. Hardly the pinnacle of application design but it worked fine.

This option is now gone and I am at a loss for a good alternative. What mechanism should I use when communicating between views that are not in a child/parent hierarchy? Everything I have come up with is clunky and triggers my sense that "Ember has a better way".

In short I want:

  • A toolbar-button to trigger an event
  • The main view to react to this and perform some updates on parts of itself.
  • The main view to NOT re-render in the Ember sense of the word as would through routing. It uses a drawing library and integrating all it's properties and behavior into Ember models and controllers would not be a lot of fun.
  • The toolbar and the main view share a parent view but are on different "branches".

Poor Options I am considering:

The toolbar is very much an application level concern but it does have some buttons that need to instruct specific views. One option I see within Ember is to nest the toolbar under the "main" view. This seems wrong for some of it's other functions.

Communication could be handled by a controller (and possibly even a model) that would hold properties that the toolbar sets and the "listening" view reacts to and resets the value of. This sounds like abuse of the controller and model purposes and like a pretty poor event listener setup.

I could make the drawing library an application global as App.Drawing or something but that does also seems bad. It would also mean that the actions still would not be able to make use of any data in the view to update the drawing library with.

Any suggestions?

Camper answered 30/1, 2013 at 19:7 Comment(0)
R
2

What mechanism should I use when communicating between views that are not in a child/parent hierarchy?

In a typical ember application this communication should happen between controllers. Otherwise "Poor Option 2" is on the right track:

Communication could be handled by a controller (and possibly even a model) that would hold properties that the toolbar sets and the "listening" view reacts to and resets the value of.

Consider using two controllers. Toolbar actions will target the ToolbarController, which is responsible for maintaining the toolbar's state and for changing main in response to user action. ToolbarController should declare a dependency on MainController via the needs property. For example:

App.ToolbarController = Ember.Controller.extend({
  needs: ['main'],
  buttonOneGotAllPressed: function() {
    main = this.get('controllers.main');
    main.turnOffAnOption();
    main.makeSomeOtherChange();
  }
}); 

Now MainController can be focused on the state of MainView. It should not be aware of ToolbarController or it's buttons.

This sounds like abuse of the controller and model purposes and like a pretty poor event listener setup.

Agreed it would likely be an abuse of model purposes but it is exactly what controllers are for.

This is definitely not an event-listener setup, but that does not seem a good fit in your case. The toolbar you describe seems to exist only to interact with the main view, so it makes sense to have a toolbar controller that depends on main and interacts with it directly.

If the components are truly decoupled then an observer (Pub/Sub) pattern might be more appropriate. See How to fire an event to Ember from another framework if that's of interest.

Rapine answered 30/1, 2013 at 20:14 Comment(3)
This is some serious magic. I could not see any reference for using 'needs' property in the documentation. Ember is full of hidden surprises, I'm not sure if that's a good thing. Extremely hard to get a mental model of the whole framework. The most frustrating thing is that there's no clear definition of responsibilities of the classes.Rozalie
Agreed, this is a very interesting feature. I would go this way immediately if I was changing some state in the main view. That could naturally be governed by a property on the controller. But when the thing I want to trigger on the view is more akin to "blink", "bounce" and such things I am feel less comfortable linking that to a property. E.G. It would be a property called "is_bouncing" that the controller would change to true and the view reset to false immediately upon seeing it being true. They would basically be booleans acting as triggers instead of representing any state.Camper
Adding a note here for future reference: this is now documented emberjs.com/guides/controllers/dependencies-between-controllersOcarina

© 2022 - 2024 — McMap. All rights reserved.