AngularJS NgRepeat + NgClass

by JakobJingleheimer

HTML

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.js"></script>
<div ng-controller="MyController">
    <p>{{mem}}</p>
    <ul>
        <li ng-class="{'active': $parent.mem.A == $key, 'not-active': $parent.mem.A && $parent.mem.A != $key}" ng-repeat="($key, A) in As" ng-click="$parent.mem.A = $key">
            <p>{{A.x}}</p>
            <button ng-click="$parent.mem.A = $parent.findInHash($event,'prev','A')">Activate previous</button>
        </li>
    </ul>
</div>

<pre>
Instructions:
    1. Click any row
    2. Click its 'Activate previous' button.

The `findInHash` function returns the correct value, yet the scope value does not change.
</pre>

CSS

li {
    cursor: pointer;
}

pre {
    margin: 1em 0;
    word-wrap: break-word;
}

li:nth-child(odd) {
    background: #ccc;
}
li:nth-child(even) {
    background: #666;
    color: white;
}
.active {
    background: red !important;
}
.not-active {
    opacity: 0.5;
}

JavaScript

angular.module('MyApp', [])
    .controller('MyController', [
    '$scope',

function MyController($scope) {
    $scope.mem = {
        A: '',
        B: '',
        C: ''
    };
    $scope.As = {
        bar: { x: 'bar-x', y: 'bar-y', z: 'bar-z' },
        foo: { x: 'foo-x', y: 'foo-y', z: 'foo-z' },
        qux: { x: 'qux-x', y: 'qux-y', z: 'qux-z' }
    };
    $scope.Bs = {};
    $scope.Cs = {};

    $scope.findInHash = function ($event, dir, attr) {
        $event.stopPropagation();
        $event.preventDefault();
        
        var hash = $scope[attr+'s'],
            current = $scope.mem[attr],
            keys = Object.keys(hash),
            i = keys.indexOf(current),
            n = keys.length-1;

        if (dir === 'prev') {
console.log('prev');
            if (i > 0) {
                return keys[i - 1];
            }
            return keys[n]; // the last key
        } else {
            if (i !== n) {
                return keys[i + 1];
            }
            return keys[0];
        }
    };
}]);