[英]ngSrc updates on ngClick, but not on keydown event handler
I am working on a live map type application that has some buttons to navigate (eg pan, zoom, etc.). 我正在开发一个实时地图类型的应用程序,它有一些导航按钮(例如平移,缩放等)。 I added a keydown event handler to allow keyboard control.
我添加了一个keydown事件处理程序以允许键盘控制。 The event handler calls the same method.
事件处理程序调用相同的方法。
I found it odd that the buttons are snappy and reliable in their response to load the image, but the keydown response is terribly slow. 我发现奇怪的是按钮在加载图像的响应中是活泼可靠的,但是keydown响应速度非常慢。 Now, I actually think the image update was due to the
$interval
service that was repeatedly fetching it and not from the keydown event at all. 现在,我实际上认为图像更新是由于
$interval
服务重复获取它而不是来自keydown事件。 Note: I already handle stale cached images (was a separate issue) by appending the url with a unique data like date/time. 注意:我已经通过在url附加日期/时间等唯一数据来处理过时的缓存图像(这是一个单独的问题)。
I added console logging to ensure that the imgUrl
is actually changing, and it is. 我添加了控制台日志记录以确保
imgUrl
实际上正在发生变化,而且确实如此。 It seems that the button click is causing ngSrc to re-render with the updated imgUrl
, but the keyboard event is not. 似乎按钮单击导致ngSrc使用更新的
imgUrl
重新渲染,但键盘事件不是。 Here is a simplified test app that recreates the same behavior with a button and the 't' key and in this case they keydown event: 这是一个简化的测试应用程序,它使用按钮和't'键重新创建相同的行为,在这种情况下,它们是keydown事件:
javascript JavaScript的
var myApp = angular.module("myApp", ['ngMaterial'])
.controller("myCtrl", function ($scope)
{
$scope.isToggled = false;
$scope.Toggle = function ()
{
console.log("Toggle(Start): " + $scope.imgUrl);
if ($scope.isToggled)
{
$scope.imgUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/7/74/Grassland_wiki.jpg/640px-Grassland_wiki.jpg";
}
else
{
$scope.imgUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/0/01/Monotropa_uniflora_03769.jpg/640px-Monotropa_uniflora_03769.jpg";
}
$scope.isToggled = !$scope.isToggled;
console.log("Toggle(End): " + $scope.imgUrl);
};
$scope.ProcessKey = function (e)
{
if (e.key === "t")
{
$scope.Toggle();
}
};
$scope.Toggle();
document.addEventListener("keydown", $scope.ProcessKey);
});
html HTML
<div ng-controller="myCtrl" ng-app="myApp">
<md-button class="md-raised" ng-click="Toggle()">Toggle</md-button>
<img id="testImg" ng-cloak ng-src="{{imgUrl}}">
</div>
I'm stumbling through javascript and angularjs in support of a C# application which is where most of my experience is. 我正在使用javascript和angularjs来支持C#应用程序,这是我的大部分经验。
I am not sure what the root cause is. 我不确定根本原因是什么。 Perhaps it is something to do with the javascript event listener referencing a
$scope
function variable/expression? 也许这与引用
$scope
函数变量/表达式的javascript事件监听器有关? Part of that dependency is that in my main app, I'm using the $http
service to get the image. 部分依赖是在我的主应用程序中,我使用
$http
服务来获取图像。
Is there an alternative to the way I'm doing this? 有没有替代我这样做的方式? Is there a way to force the image to rerender?
有没有办法强迫图像重新渲染?
Because you adding an event outside AngularJS
, Angular will never know that the $scope
property changed. 因为您在
AngularJS
之外添加事件,所以Angular永远不会知道$scope
属性已更改。 So you manually have to tell Angular something has changed using $scope.$apply()
. 因此,您必须手动告诉Angular使用
$scope.$apply()
更改了某些内容$scope.$apply()
。
var myApp = angular.module("myApp", []) .controller("myCtrl", function ($scope) { $scope.isToggled = false; $scope.Toggle = function () { console.log("Toggle(Start): " + $scope.imgUrl); if ($scope.isToggled) { $scope.imgUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/7/74/Grassland_wiki.jpg/640px-Grassland_wiki.jpg"; } else { $scope.imgUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/0/01/Monotropa_uniflora_03769.jpg/640px-Monotropa_uniflora_03769.jpg"; } $scope.isToggled = !$scope.isToggled; console.log("Toggle(End): " + $scope.imgUrl); }; $scope.ProcessKey = function (e) { if (e.key === "t") { $scope.Toggle(); $scope.$apply(); } }; $scope.Toggle(); document.addEventListener("keydown", $scope.ProcessKey); });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-controller="myCtrl" ng-app="myApp"> <button class="md-raised" ng-click="Toggle()">Toggle</button> <img id="testImg" ng-cloak ng-src="{{imgUrl}}"> </div>
You could use $scope.apply(handler)
你可以使用
$scope.apply(handler)
$scope.apply(function () {
// Angular is now aware that something might of changed
$scope.changeThisForMe = true;
});
Note: I prefer the $scope.apply();
注意:我更喜欢
$scope.apply();
solutions because they do not require a site element to be in focus first. 解决方案,因为它们不需要首先关注网站元素。
Because I'm stubborn, I found another solution with the goal of staying in AngularJS and thought I would provide it for completeness. 因为我很顽固,我找到了另一个解决方案,目标是留在AngularJS,并认为我会提供完整性。
Based on the following post: AngularJS ng-keydown directive only working for <input> context? 基于以下帖子: AngularJS ng-keydown指令仅适用于<input>上下文?
I removed the following line from the javascript: 我从javascript中删除了以下行:
document.addEventListener("keydown", $scope.ProcessKey);
I made the following tweak to the html using ng-keydown
which I previously could only get working on input tags. 我使用
ng-keydown
对html进行了以下调整,之前我只能使用输入标签。 I added tabindex
which allows an item to be in focus and solves the input tags problem: 我添加了
tabindex
,它允许项目处于焦点并解决输入标签问题:
<div ng-controller="myCtrl" ng-app="myApp" tabindex="0" ng-keydown="ProcessKey($event);">
<md-button class="md-raised" ng-click="Toggle()">Toggle</md-button><br>
<img id="testImg" ng-cloak ng-src="{{imgUrl}}">
</div>
Note that I could not get it to work on the body tag. 请注意,我无法让它在body标签上工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.