en una directiva, $ watch dispara dos veces y vuelve a newValue al valor original de pre $ watch firing

Estoy bastante seguro de que estoy haciendo algo mal debido a mi pequeña experiencia con angular. Probablemente la respuesta ya está en algún lugar en stackoverflow, y no estoy haciendo (googlear) las preguntas correctas.

Tengo esta directiva bastante simple. Es solo un intervalo con cuatro estados, que quiero cambiar con cada clic en el intervalo. Cada clic avanza el estado hacia adelante y luego retrocede. Cada estado tiene una clase css diferente. Quiero que se cambien los valores en el modelo principal cada vez que se cambie el valor de la directiva (de ahí el "=" en la declaración de alcance del aislamiento, ¿verdad?).

Pongo un reloj en el valor para cambiar la clase, de modo que la clase css se actualice cada vez que cambia el valor.

Ahora, el problema es que cuando hago clic, el reloj se activa con newValue, pero luego el reloj vuelve a sonar con newValue igual al valor anterior al clic.

Creo que esto es algo que tiene que ver con la verificación sucia y la conexión al modelo del controlador principal, pero entonces, ¿cuál es la forma angular correcta de hacer esto? ¿Y / o hay una forma mejor, más angular, de obtener el mismo resultado?

aquí la directiva:

.directive('square', function() {
    return {
        restrict: 'E',
        transclude: true,
        scope : {
            value : '=',
        },
        link: function(scope, elm, attrs, ctrl) {

            scope.valueToClass = function(value) {
                var result = 'square-empty';
                    if (value == '1') {
                        result = 'square-temp';
                    } else if (value == '2') {
                        result = 'square-confirmed';
                    } else if (value == '3') {
                        result = 'square-critical';
                    }
                return 'block-'+result;
            }

            scope.$watch('value', function(newValue, oldValue) {
                scope.blockClass = scope.valueToClass(newValue)

            }, true);

        },
        controller: function($scope, $element, $attrs) {
            $scope.changeValue = function() {
                $scope.value = ($scope.value+1) % 4;
            }
        },
        template : '<span class="{{blockClass}}"  ng-click="changeValue();">'+'</span>',
        replace: true
    };
});

aquí>> el violín <<

Respuestas a la pregunta(3)

Su respuesta a la pregunta