How to organize my Marionette.js-app the right way?

530 views Asked by At

I'm working on my first large front-end application built with Marionette.js framework. By now I have module BlogApp, which is small blog sub-appliaction with only 2 methods list(to list all posts) and show (to display single post by id):

@MainApp.module "BlogApplication", (BlogApplication, App, Backbone, Marionette, $, _) ->

    class BlogApplication.Router extends Marionette.AppRouter
        appRoutes:
            "blog"              : "list"
            "posts/:id"         : "showPost"

    API =

        list: ->
            BlogApplication.List.Controller.list()

        showPost: (id, post) ->
            BlogApplication.Show.Controller.showPost id, post

    App.addInitializer ->
        new BlogApplication.Router
            controller: API

    App.vent.on "blog:post:clicked", (post) ->
        App.navigate Routes.post_path(post.id)
        API.showPost post.id, post

    App.on "blog:list": ->
        App.navigate("blog")
        API.list()

My folders are organized like this:

--blog
  -blog_app.js
  --list
    --templates
     -blog_sidebar.template
     -blog_panel.template
     -blog_layout.template
     -blog_post.template
    -list_controller.js
    -list_view.js
  --show
    --templates
     -blog_sidebar.template
     -blog_panel.template
     -blog_layout.template
     -blog_post.template
    -show_controller.js
    -show_view.js

Everything works fine. The only difference between the show and list pages - is displaying one full post instead of listing them all. Now I have 2 controllers and I'm duplicating my templates for show and list methods, which is totally not a good practice. But I also don't think that I should implement my show method in List.Controller - it will help me to use same templates, because it will break my application infrastructure and in future, when I have to add some features, for example - comments,tags etc, it will mess up everything. How should I organize my blog module the right way?

1

There are 1 answers

0
Trace On

The way I organise my code has been working overall well without any memory leaks (afaik) until now.
I will share this with you and for any people who might find this useful.
I will also provide some supplementary information on how I manage the memory.

1) For the folder structure I have something like:

  • folder: apps
    • folder: app_blog.js
      • folder: layouts (for views + templates)
      • folder: views (for views + templates)
      • folder: => here comes the name of one or more sub-apps
        • folder: layouts
        • folder: views
        • file: ctr_list.js => a Marionette controller
      • file: app_blog
  • folder: components
  • folder: models
  • folder: vendor
  • file: main.js
  • file: app.js

In my application, the app_blog is an app (folder) that uses an app_name.js file to manage the routes, and bootstrap the subapps, and controllers to manage subsections of the app.

When a route is hit:

//1. render layout 
var layout = new Layout(); 
layout.render(); 

//2. instantiate controller & tell the controller what to do 
var ctr_List = new Ctr_List(); 
ctr_list.showList(); 

A controller in my application has the following format:

define(["backbone", "marionette", "jquery", "zwoop", "apps/app_blog/list/views/some_view"
], 
function(Backbone, Marionette, $, Zwoop, Some_View){ 

    var Ctr_List = Marionette.Controller.extend({ 

        initialize: function(options){ 
            this.events(); 
            this.region = new Marionette.Region({ el: #some-region }); 
            //Define more regions if you need to 
        }, 

        events: function(){ 
            app.on("reset", _.bind(function(){ this.close(); }, this)); 

            app.on("dosomething", _.bind(function(param){ this._doSomething(); }, this)); 
            this.events(); 

            this.region.on("show", _.bind(function(){ this.activatePlugin(); }, this)); 
        }, 

        showList: function(){ 
            this._showList(); 
        }, 

        _showList: function(){ 
            //Render the list 
            var some_view = new Some_View(); 
            this.region.show(some_view); 
        }, 

        _doSomething(param){

        }, 

        _activatePlugin(){
            //eg. $("#date-input").datepicker(); 
        }, 

        //Unbind all events 
        onClose: function(){ 
            app.off("doSomething"); 
            this.region.off("show"); 
        } 

    }); 

    return Ctr_List; 
}); 

Then when another route gets triggered and another app is started, I will call app.trigger("reset") if necessary to close the controller and unbind events that were bound by the controller.

So far, this has worked well for me.