Директива AngularJS - ng-class в ng- repeat - это должен быть $watcher для переключения стиля?

В настоящее время я реализую шип, чтобы углубить мое понимание угловых директив и т. Д.

Предпосылка состоит в том, чтобы создать список наблюдения FX по ряду валютных пар.

Мой фид данных настроен для моих обновлений цен через socket.io.

Камнем преткновения, который у меня есть, является возможность изменять CSS в зависимости от изменения цены, то есть стрелка вверх для вверх, стрелка вниз для вниз.

Я чувствую, что мне нужна функция наблюдателя, но я не мог понять, с чего начать, поэтому искал какое-то выражение в ng-классе, чтобы выполнить работу... но метод не только начал выглядеть как $watcher, но и был ошибочным поскольку сохранение предыдущей цены в моей директиве означало, что всегда было только одно старое значение, а не одно для каждой цены.

Вот мой вопрос: есть ли решение с помощью ng-class или в настройке функции $watcher?

Вот мой код...

HTML шаблон

<div ng-repeat="rate in rates" ng-click="symbolSelected(rate)">
        <div class="col-1-4">
            {{rate.symbol}}
        </div>
        <div class="col-1-4">
            <span ng-class='bullBear(rate.bidPoint)' ></span> {{rate.bidBig}}<span class="point">{{rate.bidPoint}}</span>
        </div>

        <div class="col-1-4">
            <span ng-class='bullBear(rate.offerPoint)' ></span> {{rate.offerBig}}<span class="point">{{rate.offerPoint}}</span>
        </div>

        <div class="col-1-4">
            {{rate.timeStamp | date : 'hh:mm:ss'}}
        </div>

    </div>

Моя директива в настоящее время выглядит следующим образом... как уже отмечалось, это не будет работать, а метод bullBear начинал выглядеть как функция $watcher.

.directive('fxmarketWatch', function(fxMarketWatchPriceService){

        return {

            restrict:'E',
            replace:'true',
            scope: { },

            templateUrl:'common/directives/fxMarketWatch/marketwatch.tpl.html',

            controller : function($scope, SYMBOL_SELECTED_EVT,fxMarketWatchPriceService){

                $scope.symbolSelected = function(currency){
                    $scope.$emit(SYMBOL_SELECTED_EVT,currency);
                }

                $scope.bullBear = function(newPrice){


                    if ($scope.oldPrice> newPrice ){

                           return ['glyphicon glyphicon-arrow-down','priceDown'];
                     }
                     else if ($scope.oldPrice > newPrice ){

                           return ['glyphicon glyphicon-arrow-up','priceUp'];
                     }

                }


                $scope.$on('socket:fxPriceUpdate', function(event, data) {

                    $scope.rates  =  data.payload;

                });
            }

        }

    })

2 ответа

Решение

Я рекомендую вам использовать оба ng-class а также $watcher, Эти два могут фактически дополнить друг друга:

ОБНОВЛЕНИЕ: чтобы код работал с ng-repeatнам нужно перенести всю логику CSS классов на другую controller:

app.controller('PriceController', function($scope) {
    // we first start off as neither up or down
    $scope.cssBid = 'glyphicon';
    $scope.cssOffer = 'glyphicon';

    var cssSetter = function(newVal, oldVal, varName) {
        if (angular.isDefined(oldVal) && angular.isDefined(newVal)) {
            if (oldVal > newVal) {
                $scope[varName] = 'glyphicon glyphicon-arrow-down priceDown';
            } else if (newVal > oldVal) {
                $scope[varName] = 'glyphicon glyphicon-arrow-up priceUp';
            } else {
                $scope[varName] = 'glyphicon';
            }
        }
    };

    // watch for change in 'rate.bidPoint'
    $scope.$watch('rate.bidPoint', function(newVal, oldVal) {
        cssSetter(newVal, oldVal, 'cssBid');
    });
    // watch for change in 'rate.offerPoint'
    $scope.$watch('rate.offerPoint', function(newVal, oldVal) {
        cssSetter(newVal, oldVal, 'cssOffer');
    });
});

Далее мы связываем это PriceController на ng-repeat дела. Тем самым Angular создаст один controller экземпляр для каждого rate в rates, Итак, на этот раз rate.bidPoint а также rate.offerPoint должен быть доступен для $watch-ную:

<div ng-repeat="rate in rates" ng-click="symbolSelected(rate)" ng-controller="PriceController">
    <div class="col-1-4">
        <span ng-class='cssBid'></span> {{rate.bidBig}}<span class="point">{{rate.bidPoint}}</span>
    </div>

    <div class="col-1-4">
        <span ng-class='cssOffer'></span> {{rate.offerBig}}<span class="point">{{rate.offerPoint}}</span>
    </div>
</div>

Теперь контроллер директивы будет намного короче, чем раньше:

controller: function($scope, SYMBOL_SELECTED_EVT, fxMarketWatchPriceService){
    $scope.symbolSelected = function(currency) {
        $scope.$emit(SYMBOL_SELECTED_EVT, currency);
    }

    $scope.$on('socket:fxPriceUpdate', function(event, data) {
        $scope.rates = data.payload;
    });
}

Вы можете изменить ng-class и переместите логику в представление, потому что стили и размещение классов не должны выполняться в коде.

<div class="col-1-4">
  <span class="glyphicon" ng-class="{'glyphicon-arrow-up priceUp': oldPrice > rate.bidPoint, 'glyphicon-arrow-down priceDown':oldPrice > rate.bidPoint}"></span> {{rate.bidBig}}<span class="point">{{rate.bidPoint}}</span>
</div>

Или вот так:

<span class="glyphicon {{oldPrice > rate.bidPoint ? 'glyphicon-arrow-down priceDown':'glyphicon-arrow-up priceUp'}}></span> {{rate.bidBig}}<span class="point">{{rate.bidPoint}}</span>
Другие вопросы по тегам