Should discourse have so much logic in their modal views?

It seems as if the Discourse has put a lot of logic in their modal views (as in Ember.View instances)

One example is the the account creation view.

Is this considered good practice if not, how would this be modeled better?

1 Like

I prefer to move as much logic as possible out of the view, and into to the view’s controller; thus making my views as dumb as possible.

To ensure my views stay dumb, I create a controller for each view. Instead of using {{view Ember.View}} I use view/controller pairs by utilizing route.render() or {{render}} or {{control}}. That way every view has a corresponding controller. (Unless I don’t need any logic such as Ember.TextField which only does value binding).

I also try to make my controllers as thin as possible by moving events into the route. Unfortunately if a view does not represent a higher state (and thus no route exists for it), and might be re-used in any route, I either use App.ApplicationRoute to handle its events, or handle its events in its controller.

I am interested to know if that is considered good practice.

1 Like

I would say no! And I’m the one responsible for that :slight_smile:

When I initially built that stuff I had no idea how to wire a controller up to something that popped up dynamically. So I ended up treating a modal view as responsible for everything in the modal.

Now I have a much better grasp on Ember and I’d like to convert each modal to have a proper controller associated with it. I consider it technical debt, so please don’t copy our approach :slight_smile:

6 Likes

This is very well aligned with how I’ve tried to do things. That’s why I was a bit surprised when Discourse, the big ember flag ship, had so much stuff in the views.

I think this might be caused by how their modal system works.

They have a long lived Discourse.ModalView which is rendered into the application template (initially hidden). This view is a ContainerView which uses the currentViewBinding to trigger display of the modal whenever its currentView property changes. And the bootstrap modal plugin takes care of hiding the modal again when appropriate.

The ModalView has a corresponding ModalController which (i think) is the go to controller for the lifespan of the modal (which is forever). This is the controller all modals currently have as their context.

I guess it’s not straight forward to make sure the individual views put inside the currentView properties gets wired up to a controller of their own. And I suppose it’s an easy way out to just put everything in the individual modal views.

That would be awesome! There’s not a lot of public ember apps out there for people just starting with ember (like me) and Discourse has become the de facto answer for example apps.

I would love to see examples of things, like modals, that doesn’t necessarily qualify as stand alone routes / urls where gluing stuff together isn’t handled by the router. How to deal with dynamically adding and removing isolated components like that, and perhaps give them a StateManger of their own, e.g. a wizard flow in a modal window to make sure one can handle actions/events in a nice way.

2 Likes

I’m very interested in how this should be handled too. Especially when the interaction within the view in question is non-trivial and perhaps calls for a statemanager of its own.

1 Like

How would you do it today?

I probably will refactor it soon – but the idea would be that every modal has a controller and all the logic for interacting with the modal goes into the controller instead of the view as it currently is.

I think a good, clean approach (especially with complex modals) is to have a stateManager control when a modal is shown or hidden, and more precisely, when a modal is inserted or removed from the DOM.

My basic architecture for this in pseudocode is:

  • create a modalStateManager object and an instance that is globally accessible
  • put an outlet (e.g., {{outlet modal}} for the modal in your main template (i.e., the template where the user will click to open the modal)
  • when user clicks to open modal, call an open function on your modalStateManager instance
  • open function renders the modalView, modalTemplate and modalController into the modal outlet. (in old ember, you could do this with connectOutlets, I believe the new way is with renderTemplate)

you’d then also have some function that closes modal (and can destroy the modal).

I actually did a presentation on this topic at the Ember.js meetup: it’s old ember, but the architecture should still be valuable. https://speakerdeck.com/ashaegupta/managing-modals-and-other-non-url-based-views-in-ember-dot-js

8 Likes