Command Pattern With Angular

Uses a command pattern to create decoupled commands that can be bound to buttons, or menu items.

HTML

<script src="http://code.angularjs.org/1.2.0-rc.3/angular.min.js"></script>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
<script src="http://code.angularjs.org/1.2.0-rc.3/angular-route.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
<div data-ng-controller="Ctrl as ctrl" class="container">
    <div class="row">
        <div class="col-md-6">
             <h2>Buttons</h2>

            <button type="button" class="btn btn-primary" data-ng-repeat="cmd in ctrl.commands" data-ng-click="cmd.execute({msg:'From Button'})" data-ng-disabled="!cmd.canExecute()">{{cmd.name}}</button>
        </div>
        <div class="col-md-6">
             <h2>Dropmenu</h2>

            <div>
                <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">Dropdown <span class="caret"></span>

                </button>
                <ul class="dropdown-menu">
                    <li data-ng-repeat="cmd in ctrl.commands" data-ng-class="{disabled:!cmd.canExecute()}"><a href="" data-ng-click="cmd.execute({msg:'From Dropdown'})">{{cmd.name}}</a>
                    </li>
                </ul>
            </div>
        </div>
    </div>
</div>

JavaScript

var Controllers;
(function (Controllers) {

    var Ctrl = function (commandService) {
        this.commands = [
        commandService.getCommand('Home'),
        commandService.getCommand('Toggle Admin'),
        commandService.getCommand('Admin')];
    };

    Ctrl.$inject = ['commandService'];

    Controllers.Ctrl = Ctrl;

}(Controllers || (Controllers = {})));

var Services;
(function (Services) {

    var CommandExecutor = function ($injector, cmd) {
        this.name = cmd.name;
        this.cmd = cmd;
        this.$injector = $injector;
    };

    CommandExecutor.prototype.canExecute = function () {
        return this.$injector.invoke(this.cmd.canExecute, this.cmd);
    };

    CommandExecutor.prototype.execute = function (params) {
        if(this.canExecute()){
            this.$injector.invoke(this.cmd.execute, this.cmd, params);
        }
    };

    CommandExecutor.$inject = ['$injector', 'cmd'];

    var CommandService = function ($injector) {
        this.$injector = $injector;
        this.commands = {};
    };

    CommandService.prototype.executeCommand = function (commandName, options) {
        var cmd = this.getCommand(commandName);

        if (cmd.canExecute()) {
            cmd.execute(options);
        }
    };

    CommandService.prototype.getCommand = function (commandName) {
        return this.commands[commandName];
    };

    CommandService.prototype.addCommand = function (cmd) {
        if (angular.isDefined(cmd)) {
            this.commands[cmd.name] = this.$injector.instantiate(CommandExecutor, {
                cmd: cmd
            });
        }
    };

    CommandService.prototype.createUrl = function (url, params) {
        if (typeof params === 'undefined') {
            params = {};
        }

        return url.replace(/\:(\w+)/g, function (match, index) {
            return typeof params[index] !== 'undefined' ? params[index] : match;
        });
    };

    CommandService.$inject = ['$injector'];

   ...