Garbage Mashers, Power + Parsed Filter

How to do a group-by in Angular using external AngularFilter library. A custom directive for power button that internally parses a Filter used in this example from a design/implementation problem I am having. Looking for the correct Design Pattern in AngularJS.

by Andrew Philips

HTML

<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.24/angular.js"></script>
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.0.4/css/bootstrap-combined.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.4.8/angular-filter.min.js"></script>
<table ng-controller="MasherCtrl" class="table-condensed">
    <thead>
        <tr class="hline-bot">
            <th colspan=3>
                <h3>Garbage Mashers, <small>Power + Parsed Filter</small></h3>
            </th>
        </tr>
        <tr>
            <th>Level</th>
            <th>Masher</th>
            <th>Power</th>
        </tr>
    </thead>
    <tbody ng-repeat="(level, mashers) in allMashers | groupBy: 'level'">
        <tr ng-if="mashers.length>1" class="hline-bot-grp">
          <td>{{level}}</td>
          <td></td>
          <td class="power">
            <power-button group="mashers"></power-button>
          </td>
        </tr>

        <tr ng-repeat="masher in mashers" ng-class="{ 'hline-bot': $last}">
          <td><span ng-if="$first==1&&mashers.length<2">{{masher.level}}</span></td>
          <td>{{masher.name}}</td>
          <td class="power">
            <power-button masher="masher"></power-button>
          </td>
        </tr>
    </tbody>
</table>

CSS

th, .power {
    text-align: center
}
tr th {
    font-weight: bold
}
.indicate-off {
    color: #B22222;
}
.indicate-unk {
    color: #FFA500;
}
.indicate-on {
    color: #228B22;
}
.bwy-button {
    /* Use this to style new button with no border. */
    border: none;
    background: none;
    padding: 5px 5px;
}
tr.hline-bot td, tr.hline-bot th {
    border-bottom:1px double #999;
}
tr.hline-bot-grp td {
    border-bottom:1px double #CCC;
}
td {
    min-width: 125px;
}

JavaScript

(function () {
    var rotatePower = function(v) { return {'-1':0,'0':1,'1':0}[v]; };
    var colorMap = function(state) { return { '1':'indicate-on', '-1':'indicate-unk', '0':'indicate-off'}[state]; };

    angular.module('myApp', ['angular.filter'])
        .controller('MasherCtrl', ['$scope', '$parse', '$log', function ($scope, $parse, $log) {
            $scope.allMashers = {
                1: { id: 1, name: "3263827", power: 1, level: "Detention" },
                2: { id: 2, name: "10 Fwd",  power: 1, level: "Club"  },
                3: { id: 3, name: "00001",   power: 0, level: "Overbridge" },
                4: { id: 4, name: "8675309", power: 1, level: "Club" },
                5: { id: 5, name: "THX1138", power: 0, level: "Detention" }
             };

            // This would dispatch an AJAX call performing Masher power
            // change at server.  Either that module subscribes to
            // ui.power event or has an API that this module calls.
            $scope.$on('ui.power', function(e,o) { $log.log(e.name + ": " + angular.toJson(o)); });
        }])
        .directive('powerButton', ['$parse', function ($parse) {
	    return { restrict: 'E',
		     scope:    true,
		     template: '<button class="bwy-button" ng-click="myOnClick()"><span ng-class="btnColor" class="glyphicon glyphicon-off"></span></button>',
		     link: function(scope, element, attrs) {
			 var stateChange;

			 if (attrs.group !== undefined) {
			     var getGroup = $parse(attrs.group);

			     // click changes power on mashers, $emit for AJAX
			     scope.myOnClick = function() {
				 var mashers = getGroup(scope.$parent);
				 if (mashers.length < 1) return;

				 var nv = rotatePower(scope.st);
				 angular.forEach(mashers, function(v) { v.power = nv; });
				 scope.$emit('ui.power', { level:mashers[0].level,mashers:mashers,value:nv });
			     };

			     // Create group filter to watch
			     stateChange = $parse("("+attrs.group+")|map:...