2013-12-13 7 views
3

Я написал директиву, которая захватывает события клавиатуры, а на некоторых ключах я обновляю некоторые объекты в области. Идея состоит в том, чтобы перемещать вверх и вниз по массиву и отображать выбранные данные о строках. Проблема заключается в том, что страница не обновляется, пока я не сделаю еще одно действие, которое обновляет страницу. Как я могу заставить это?Как обновить страницу angularjs после обновления области?

Вот директива:

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) примет элемент с заданным идентификатором и отображать его в другой части страницы. Часть, которая не обновляется до тех пор, пока не будет выполнено другое действие, например, нажатие кнопки. Возможно ли принудительное обновление страницы?

Вот скрипка, которая воспроизводит: http://jsfiddle.net/gM2KF/1/ Если вы нажмете на кнопку, счетчик будет обновлен. Если вы нажмете любую клавишу, ничего не появится. Но вы снова нажимаете кнопку, вы видите, что счетчик был обновлен событием клавиатуры, но не отображался.

ответ

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 цикл и разрешить изменения привязки.

+0

Какова наилучшая практика: вызовите 'scope. $ Apply()' после изменения или, как предполагает m59, оберните код в $ apply? Какая разница? – Antoine

+2

@Antoine лучше обернуть часть кода с помощью 'scope. $ Apply (function() {/ ** /}', чем просто вызвать 'scope. $ Apply();' вызывать цикл diggest только для части кода –

+0

Хмм, извинения, кстати ... Я бы просто прокомментировал ваш ответ, но в то время не было ответов. Я никогда не видел, чтобы это делалось раньше. – m59

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

Это единственный пример, который печатает события основаны на вашем примере :

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 метод на каждом ключевом событии.

Смежные вопросы