Angular SortableTable

Using directive

by Alex

HTML

<script type="text/javascript" src="http://docs-next.angularjs.org/angular-0.10.5.min.js" ng:autobind></script>
    
<table ng:controller="SortableTableCtrl" ng:cloak>
    <thead>
    <tr>
        <th ng:repeat="(col, hdg) in head">
            <span ui:sort='col'>{{hdg}}</span>
        </th>
    </tr>
    </thead>
    <tbody>
    <tr ng:repeat="row in body.$orderBy(selected,reverse)">
        <td>{{row.a}}</td>
        <td>{{row.b}}</td>
        <td>{{row.c}}</td> 
    </tr>
    </tbody>
</table>

CSS

td { padding: 0.2em 1em; }
th { text-align: center; cursor: pointer; }
th span { padding-right: 2px; } /* gap so asc/desc images are not flush */
thead {
    border-bottom: 2px solid black; 
    cursor: pointer;  
}

/* http://www.greywyvern.com/code/php/binary2base64 */

th {
    min-width: 100px;
    text-align: center;
}
span.desc:after {
     content:...

JavaScript

angular.directive('ui:sort', function(expression, compileElement) {
    return function(linkElement) {
        var scope = this;
        var pscope = scope.$parent;
        var el = linkElement;

        el.bind('click', function(event) {
            if (!pscope.selected || pscope.selected != scope.col) {
                pscope.selected = scope.col;
                pscope.reverse = false;
            } else {
                pscope.reverse = !pscope.reverse;
            }
            pscope.$digest(); // update view
        });

        scope.switchClass = function(remClass, addClass) {
            el.removeClass(remClass);
            el.addClass(addClass);
        }

        scope.$watch('selected', function(scope, newVal, oldVal) {
            if (scope.col !== newVal) {
                el.removeClass('desc');
                el.removeClass('asc');
            } else {
                el.addClass('asc');
            }
        });

        scope.$watch('reverse', function(scope, reverseNewVal) {
            if (scope.col === pscope.selected) {
                if (reverseNewVal) {
                    scope.switchClass('asc', 'desc');
                } else {
                    scope.switchClass('desc', 'asc');
                }
            }
        });
    };
});


function SortableTableCtrl() {
    var scope = this;
    // defaults
    scope.reverse = false;
    scope.selected = 'a';

    // model
    scope.head = {
        a: "Name",
        b: "Surname",
        c: "City"
    };
    scope.body = [
        {
        a: "Hans",
        b: "Mueller",
        c: "Leipzig"},
    {
        a: "Dieter",
        b: "Zumpe",
        c: "Berlin"},
    {
        a: "Bernd",
        b: "Danau",
        c: "Muenchen"}
    ];
}