Угловой: изменение высоты не обнаружено

0

Я написал пару директив, которые предназначены для увеличения одного из нескольких элементов до большего размера при щелчке элемента. При нажатии на увеличенный элемент следует вернуть его в нормальный размер. Когда элемент масштабируется, его схожие элементы (они все диаграммы d3) становятся невидимыми. Они восстанавливаются до видимости, когда расширенный элемент не затенен.

Вот как выглядит HTML:

<chart-container class="chart" chart-height="400" >
    <h3 class="text-center">Vehicles by year</h3>
    <div class="text-center" full-screen-toggle>
        <bar-chart bar-data="{{vehiclesByYear}}"
                    layout="{{vehiclesByYearLayout}}"
                    bar-labels="{$dy: '-.5em', $anchor: 'middle'}"></bar-chart>
    </div>
</chart-container>
<chart-container class="chart" chart-height="400">
    <h3 class="text-center">Vehicle speed distribution</h3>
    <div class="text-center" full-screen-toggle>
        <pie-chart pie-data="{{aboveBelow}}"
                   layout="{{aboveBelowLayout}}"></pie-chart>
    </div>
</chart-container>

Магия находится в контейнере-директиве элемента-элемента и директиве атрибута full-screen-toggle. Последний всегда украшает дочерний элемент внутри контейнера диаграмм. Здесь код для двух директив:

angular.module( 'MarkOlbert.fullScreenChart', [] ).directive( 'chartContainer', function () {
    return {
        restrict: 'E',
        scope: {
            chartHeight: '@chartHeight',
        },
        controller: ['$scope', '$element', '$rootScope', function ( $scope, $element, $rootScope ) {
            var zoomState = 'normal';
            var _self = this;

            this.changing = false;
            this.chartHeight = $scope.chartHeight;

            function unZoom() {
                $element.css('width', '50%' );

                _self.changing = true;
                $rootScope.$broadcast( 'chart:unzoom' );
                _self.changing = false;

                zoomState = 'normal';
            }

            function zoom() {
                $element.css( 'width', '100%' );

                _self.changing = true;
                $rootScope.$broadcast( 'chart:zoom' );
                _self.changing = false;

                zoomState = 'full';
            }

            $element.on( 'click', function () {
                switch ( zoomState ) {
                    case 'normal':
                        zoom();
                        break;

                    case 'full':
                        unZoom();
                        break;
                }
            } );

            $rootScope.$on( 'chart:unzoom', function () {
                if ( _self.changing ) return;

                $element.css( 'display', 'block' );
            } );

            $rootScope.$on( 'chart:zoom', function () {
                if ( _self.changing ) return;

                $element.css( 'display', 'none' );
            } );
        }],
    };
} );

angular.module( 'MarkOlbert.fullScreenToggle', [] ).directive( 'fullScreenToggle', function ($rootScope) {
    return {
        restrict: 'A',
        require: '^^chartContainer',
        link: function(scope,element,attrs, chartCtrl){
            element.css('height', chartCtrl.chartHeight );

            $rootScope.$on( 'chart:zoom', function () {
                if ( !chartCtrl.changing ) return;

                element.css( 'height', 1000 );
            } );

            $rootScope.$on( 'chart:unzoom', function () {
                element.css( 'height', chartCtrl.chartHeight );
            } );
        },
    };
} );

В директиве bar-chart у меня есть простые часы, которые должны реагировать на изменения высоты диаграммы:

    scope.$watch( function () { return element.height(); }, function () {
        if ( element.height() == 0 ) return;
    }, true );

Сейчас он ничего не делает, потому что я пытаюсь понять, почему он не вызван, когда полноэкранный режим изменяет высоту.

Функциональность show/hide работает так, как было разработано. Все различные прослушиватели событий в контейнере диаграмм и полноэкранном переключении вызывают, когда они должны быть, и выполняются без ошибок.

Когда chart-container изменяет ширину своего элемента, страница обновляется, как ожидалось. Но когда полноэкранный режим изменяет высоту диаграммы, ничего не происходит. Часы $ watch в бар-диаграмме никогда не срабатывают.

1 ответ

1
Лучший ответ

.on() - это метод jqLite/jQuery и не вызывает триггер цикла AngularJS.

Что происходит сейчас:

  1. Элемент нажат
  2. Вызов Zoom или Unzoom
  3. Элемент CSS изменен
  4. Событие транслируется
  5. Слушатели для вещательного события уведомляются
  6. Высота элемента изменена

Но так как цикл дайджеста никогда не запускался, наблюдатель, который проверяет высоту элемента, никогда не будет выполняться, и никакие изменения не будут обнаружены.

Вы можете использовать $apply:

$element.on('click', function() {
  $scope.$apply(function() {
    switch (zoomState) {
      case 'normal':
        zoom();
        break;

      case 'full':
        unZoom();
        break;
    }
  });
});

Ещё вопросы

Сообщество Overcoder
Наверх
Меню