如何在更新范围后更新angularjs页面?

时间:2013-12-13 16:19:00

标签: angularjs angularjs-scope

我编写了一个捕获键盘事件的指令,在某些键上我更新了作用域中的一些对象。我们的想法是上下移动一个数组并显示所选的行详细信息。问题是在我执行另一个更新页面的操作之前,页面不会更新。我怎么强迫这个?

这是指令:

LogApp.directive("keyCapture", [function(){
    var scopeInit;
    return{
        link: function(scope, element, attrs, controller){
            scopeInit = scope
            element.on('keydown', function(e){
                scopeInit[attrs.keyCapture].apply(null, [e]);                
            });
        }
    }
}]);

像这样绑定模板:

<body ng-controller="logCtrl" key-capture="movePreview">

控制器方法:

$scope.movePreview = function(e){
    if ($scope.events.length === 0)
        return;
    // Find the element 
    if (e.keyCode === 38 || e.keyCode === 40){
        console.log("Pressed %s", e.keyCode);
        var offset = 0;
        if (e.keyCode === 38 && $scope.previewIndex > 0)
            offset = -1;
        else if (e.keyCode === 40 && $scope.previewIndex < $scope.events.length -1 )
            offset = 1;

        $scope.previewIndex += offset;
        var eventId = $scope.events[$scope.previewIndex].uuid;
        $scope.showEvent(eventId);
        e.preventDefault();
    }
};

$scope.showEvent(eventId)将获取具有给定ID的项目并将其显示在页面的另一部分中。在执行其他操作之前不会更新的部分,例如单击按钮。是否可以强制更新页面?

这是一个重现的小提琴:http://jsfiddle.net/gM2KF/1/ 如果单击按钮,计数器将更新。如果按任意键,则不显示任何内容。但是再次单击该按钮,您会看到计数器已被键盘事件更新,但未显示。

3 个答案:

答案 0 :(得分:5)

如果您正在收听非角度事件:

element.on('keydown', function(e){
    scopeInit[attrs.keyCapture].apply(null, [e]);                
});

然后,要更新范围,您需要致电scope.$apply

element.on('keydown', function(e){
    scopeInit[attrs.keyCapture].apply(null, [e]); 
    scope.$apply();               
});

这将启动角度$digest周期并允许更改绑定。

答案 1 :(得分:2)

只需在$scope

中包含$scope.$apply();更改

虽然你的代码可以更干净,但这应该可以使它工作:

$scope.movePreview = function(e){
  $scope.$apply(function() {
    if ($scope.events.length === 0)
        return;
    // Find the element 
    if (e.keyCode === 38 || e.keyCode === 40){
        console.log("Pressed %s", e.keyCode);
        var offset = 0;
        if (e.keyCode === 38 && $scope.previewIndex > 0)
            offset = -1;
        else if (e.keyCode === 40 && $scope.previewIndex < $scope.events.length -1 )
            offset = 1;

        $scope.previewIndex += offset;
        var eventId = $scope.events[$scope.previewIndex].uuid;
        $scope.showEvent(eventId);
        e.preventDefault();
    }
  });
};

答案 2 :(得分:2)

这是根据您的示例打印事件的单个示例:

<强> HTML

<body ng-controller="MyCtrl" key-capture  move="movePreview()">    
    <pre>Pressed: {{previewIndex}}</pre>    
</body>

<强> JS

var app = angular.module('App', []);

function MyCtrl($scope) {   
    $scope.movePreview = function(e){        
        $scope.previewIndex = e.keyCode; 
};

}
app.$inject = ['$scope'];
app.directive("keyCapture", [function(){
    var scopeInit;
    return{
        link: function(scope, element, attrs, controller){

             element.bind('keydown', function (e) {
                scope.$apply(function(){scope.movePreview(e);});                    
            });            
        }
    }
}]);

演示 Fiddle

我们在每个关键事件上调用movePreview方法。