Search code examples
javascriptjquerychainingmethod-chainingrevealing-module-pattern

How to use Chaining with Nested, Revealing Module Patterns in JavaScript?


I'm struggling to get my head around a couple of JS patterns joined together: the revealing module pattern, and the chaining pattern.

What I would ideally like to be able to do is invoke multiple methods from a single initialising function like this:

components
    .loader()
    .menu()
    .toolbar();

And this works perfectly as long as any methods I define publicly return this;.

Things start to go wrong however when I need to nest revealing module patterns in order to expose deeper methods that are invoked outside of the initialisation like this:

components
    .menu
        .close();

The problem doing this is that menu no longer returns components, but instead returns it's child methods which means it breaks the chain at this point. Here is a "complete" example to illustrate what I am try to achieve:

var components = function () {

    var loader = function () {
        console.log("components.loader initialisation");

        return this;
    }

    var menu = function () {
        console.log("components.menu initialisation");

        var open = function () {
            console.log("components.menu.open");

            return this;
        }
        var close = function () {
            console.log("components.menu.close");

            return this;
        }

        return {
            open: open,
            close: close
        }
    }();

    var toolbar = function () {
        console.log("components.toolbar initialisation");

        return this;
    }

    return {
        loader: loader,
        menu: menu(),
        toolbar: toolbar
    }
}();

$(function () {

    components
        .loader()
        .menu()
        .toolbar();

    components
        .menu
            .open();

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

So I guess my question is, how can I use; nested, revealing modules and chaining together (if at all possible)?


Solution

  • var components = (function () {
    
    var loader = function () {
        console.log("components.loader initialisation");
    
        return this;
    };
    
    var menu = function () {
    
        var menu = function () {
            console.log("components.menu initialisation");
    		
            return this;
        };
    	
    
        menu.open = function () {
            console.log("components.menu.open");
    
            return this;
        };
    
        menu.close = function () {
            console.log("components.menu.close");
    
            return this;
        };
    
        return menu;
    };
    
    var toolbar = function () {
        console.log("components.toolbar initialisation");
    	
        return this;
    };
    
    return {
        loader: loader,
        menu: menu(),
        toolbar: toolbar
    };
    })();
    
    $(function () {
    components
    	.loader()
    	.menu()
    	.toolbar();
    
    components
    	.menu
    		.open();
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>