1
votes

I have an AMD Marionette application with an AppRouter - the AppRouter uses a simple controller object with a set of functions for all the main routes/actions in the application.

In a view, after processing a form submission I want to move the user to a different route.

What is the best approach for sending a user to a new route? Should I be calling methods in my controller directly from the views (if so my controller would be a dependency of the view)? Should I use simply set 'window.location'? Or should I be using an EventAggregator?

If I was to create an EventAggregator in my controller, how would I trigger these events in a view?


I'm following the 'Example with central vent' from the Marionette wiki:

https://github.com/marionettejs/backbone.marionette/wiki/Using-marionette-with-requirejs

2
Could you share your results? What did you choose to do in the end? I would advocate for the central vent. How did you name this event that triggered the switch to another view?thertweck
I've started but haven't finished yet, some other things came up - will update in a few weeksAlasdair McLeay
I've been wondering exactly the same thing. It doesn't seem like a good separation of concerns to have the view know about other routes/functions of the controller. It should only be concerned with events within itself.Mikel
I'd strongly recommend against calling window.location or router.navigate(path, {trigger: true}) except for extreme cases. I'm considering having the view trigger an event which the controller can bind to. Similar to the central vent idea but without the need for extending the Controller with an EventAggregator.Mikel

2 Answers

0
votes

I'm following the 'Example with central vent' from the Marionette wiki:

Example with central vent

Requiring your application everywhere can be tedious and there are usually better solutions. If you find yourself doing this a lot for the vent, you are probably better off making a separate module to act as the central app vent. Making smaller modules with fewer dependencies is generally the solution for AMD problems surrounding circular dependencies.

Vent module definition

with marionette version < 1.0.0-rc4

// vent.js
define(['marionette'],function(marionette){
  return new Marionette.EventAggregator();
})

with marionette version >= 1.0.0-rc4

// vent.js

define(['backbone.wreqr'],function(Wreqr){
  return new Wreqr.EventAggregator();
})

Usage

Now you have a 'global' vent module that doesn't explicitly depend on your application and can be depended on anywhere.

define(['vent'], function(vent) {
      vent.on('eventName', function(){});
      vent.trigger('eventName');
    })

https://github.com/marionettejs/backbone.marionette/wiki/Using-marionette-with-requirejs

0
votes

How I solved this for my own purposes was as follows (YMMD, excuse the CoffeeScript):

# Controller:
class MyController extends Backbone.Marionette.Controller
  showView: () ->
    view = new MyView()
    @listenTo view, 'show:otherview', @showOtherView
    @show(view)
  showOtherView: (href) ->
    otherView = new MyOtherView()
    @show(otherView)

 # View:
 class MyView extends Backbone.Marionette.ItemView
   events:
     'click a': 'emitShow'
   emitShow: (event) ->
     event.preventDefault()
     event.stopPropagation()
     href = @$(event.currentTarget).attr('href')
     @trigger('show:otherview', href)

Of course the href is just an example of some data you might want to grab from the view to pass as an argument into the event handler. This could be anything, or could be omitted if unnecessary. This bypasses the router entirely, so it would be up to the controller to call Backbone.navigate (without trigger:true) to update the browser URL when appropriate.