事件侦听器更改后,范围变量不会在DOM中更新

时间:2014-09-01 18:05:48

标签: angularjs

我在$ scope对象中定义了一个变量并绑定在DOM中。 页面加载时,值正确显示。我在$ window resize事件上定义了一个监听器,它在调整窗口大小时会适当地触发。我在被调用的函数中放置了一个断点,它在运行时确实具有正确的picCols值,并且它确实根据当前窗口宽度更改为新值。但是,在函数完成后,DOM不会使用新值进行更新。

这是我的控制器。观察到的变量是$ scope.picCols

.controller('AlbumEditCtrl', function($scope, $stateParams, $window) {
$scope.album = {id: 1, date: '8/23/2014', title: 'My Album 1', photos:
    [
        {url: 'img/default-placeholder.png'},
        {url: 'img/default-placeholder.png'},
        {url: 'img/default-placeholder.png'},
        {url: 'img/default-placeholder.png'},
        {url: 'img/default-placeholder.png'},
        {url: 'img/default-placeholder.png'},
        {url: 'img/default-placeholder.png'},
        {url: 'img/default-placeholder.png'},
        {url: 'img/default-placeholder.png'},
        {url: 'img/default-placeholder.png'},
        {url: 'img/default-placeholder.png'},
        {url: 'img/default-placeholder.png'}
    ]};
    $scope.photoRows = [];
    $scope.picCols = 0;

    $window.addEventListener("resize", function () {
        if(parseInt($window.innerWidth / 80, 10) != $scope.picCols)
        {
            $scope.recalculateImageColumns();
        }
    });

    $scope.recalculateImageColumns = function (){
        var photoRows = [];
        $scope.picCols = parseInt($window.innerWidth / 80, 10);
        console.log($scope.$id);
        var count = 0;
        var currentArray = -1;
        for(var i = 0; i < $scope.album.photos.length; i++){
            if(count < $scope.picCols){
                if(count == 0){
                    count++;
                    currentArray++;
                    photoRows.push({photos:[$scope.album.photos[i]]});
                }
                else{
                    photoRows[currentArray].photos.push($scope.album.photos[i]);
                    if(count == $scope.picCols-1)
                        count = 0;
                    else
                        count++;
                }
            }
        }
        angular.copy(photoRows, $scope.photoRows);
    };
    $scope.recalculateImageColumns();
});

这是DOM

<ion-view title="My BGCA">
<ion-content class="has-header padding">
    <h2>{{album.title}}</h2>
    <h5>{{album.date}}</h5>
    <h5>{{picCols}}</h5>
    <h5>{{$id}}</h5>
    <div class="row" ng-repeat="photoRow in photoRows">
        <div class="col" ng-repeat="photo in photoRow.photos"><img ng-src="{{photo.url}}" width="75" height="75" /></div>
    </div>
 </ion-content>
</ion-view>

更新 这是最终运作良好的指令。

.directive(
"ngResize",
function($window) {
    function link( $scope, element, attributes ) {
        var domElement = element[0];
        function updateImageCapacity() {

                var viewportWidth = domElement.clientWidth;
                var capacity = parseInt(viewportWidth / 80, 10);
                $scope.setImageCapacity( capacity );
        }
        updateImageCapacity();       

        window.angular.element($window).on('resize', function(){
            $scope.$apply( updateImageCapacity );
        });

        $scope.$on(
            "$destroy",
            function() {
                window.angular.element($window).off('resize');
            }
        );
    }

    return({
        link: link,
        restrict: "A"
    });

}
)

http://www.bennadel.com/blog/2476-my-approach-to-building-angularjs-directives-that-bind-to-javascript-events.htm?&_=0.9274228068534285#comments_45548

1 个答案:

答案 0 :(得分:19)

$window.addEventListener("resize", function () {
    if(parseInt($window.innerWidth / 80, 10) != $scope.picCols)
    {
        $scope.recalculateImageColumns();
        $scope.$apply(); // you need to call $apply if you do anything outside of angular context;
    }
});

Angular Way

app.directive("ngResize", function ($window) {
    return {
        scope: {
            ngResize: "="
        },
        link: function ($scope, element, attrs) {
            angular.element($window).on("resize", function () {
                $scope.ngResize = "Smith";
                $scope.$apply();
            });
        }
    }
});

添加指令

<div ng-controller="ctrl" ng-resize="name">{{ name }}</div>

DEMO