Search code examples
coffeescriptspine.js

'active' class not added when Spine.js controller stack used


I have two very simple Spine.js controllers:

class ListController extends Spine.Controller
    className: 'list'
    constructor: () ->
        super

class DetailController extends Spine.Controller
    className: 'detail'
    constructor: () ->
        super

controller stack

class Application extends Spine.Stack
    className: 'mystack'
    controllers:
         list: ListController
         detail: DetailController

and corresponding HTML markup

<div class="mystack">
    <div class="list">list</div>
    <div class="detail">detail</div>
</div>

My problem is that when controller stack instantiated

app = new Application()
app.list.active()

there is no active class added to the div.list element. Divs remain unchanged.

What is wrong with that?


Solution

  • I've just got it so I'll describe basic working example. There are several issues with the code above (caused by my misunderstanding of how Spine.js controller stack works :-)

    First, appropriate HTML element have to be associated with every controller managed by the stack. When controller stack instantiates the controller it passes only stack (i.e. itself) instance as parameter to the constructor. So controller constructor have to take it into account (e.g. like the following):

    class ListController extends Spine.Controller
        constructor: (parameters) ->
            @stack = parameters.stack
            @el = $ @stack.settings.listSelector
            super
    
    class DetailController extends Spine.Controller
        constructor: (parameters) ->
            @stack = parameters.stack
            @el = $ @stack.settings.detailSelector
            super
    

    and the stack:

    class Application extends Spine.Stack
        settings:
            listSelector: '.list'
            detailSelector: '.detail'
        controllers:
            list: ListController
            detail: DetailController
        default:
            'list'
    

    then the controller stack could be instantiated:

    app = new Application
        el: $ '.mystack'
    

    ListController will be active (i.e. corresponding div has active class added) by default and anytime later you can call @stack.detail.active() or @stack.list.active() from controller instance method to activate required controller and 'hide' (i.e. remove active class) the other(s).

    EDIT: We discussed the issue with @aschmid00. In fact, controller constructor doesn't have to set its own property @stack manually. It is done automatically when base constructor called by super. But in case of this question @el have to be set before base constructor called due to the events delegation etc.