I've implemented a filedrop directive that puts the file dropped in ngModel.
我已经实现了一个filedrop指令,该指令将文件放在ngModel中。
<filedrop data-ng-model="file"></filedrop>
I'm using the following code in my controller:
我在我的控制器中使用以下代码:
$scope.$watch('file', function(newVal, oldVal) {
if (newVal) {
var reader = new FileReader();
reader.onload = function(event) {
$scope.parseFile(newVal);
};
reader.readAsDataURL(newVal);
}
}, false);
In $scope.parseFile Im actually parsing the XLSX:
在$ scope.parseFile我实际解析XLSX:
$scope.parseFile = function(file) {
xlsxParser.parse(file).then(function(data) {
console.log("Number of columns", data.datasheet[1].length);
console.log("Number of rows", data.datasheet.length);
$scope.validationErrors = [];
$scope.brand = {
items: []
};
$scope.dataItems = [];
$scope.datasheetValidate(data.datasheet, $scope.brand);
$scope.datasheetData(data.datasheet, $scope.dataItems);
if ($scope.validationErrors.length == 0) $scope.validationErrors.push("Nice work, no validation errors");
//$scope.$apply(function(){});
}, function(err) {
console.log('error', err);
});
}
As you can see, I commented out the //$scope.$apply(function(){});
in the body....
如您所见,我注释掉了// $ scope。$ apply(function(){});在身体里....
BUT, I need it in order to have my webpage updated with the scope changes (e.g. show the validationErrors
)
但是,我需要它才能让我的网页更新范围更改(例如显示validationErrors)
How come I need the $scope.$apply
?
为什么我需要$ scope。$ apply?
3 个解决方案
#1
2
It doesn't matter that you're using $scope.$watch. That doesn't help when you're calling $scope.parseFile
from inside reader.onload
callback, which is outside of Angular realm.
你使用$ scope并不重要。$ watch。当你从reader.onload回调中调用$ scope.parseFile时,这无效,这是在Angular领域之外。
$scope.$apply
should be used inside the callback itself:
$ scope。$ apply应该在回调本身内部使用:
reader.onload = function(event) {
$scope.$apply(function(){
$scope.parseFile(newVal);
});
};
#2
0
$scope.$watch
and $scope.$apply
are complementary.
$ scope。$ watch和$ scope。$ apply是互补的。
$scope.$watch
registers a new watcher on the scope. Whenever there's a digest cycle, the watch function runs.
$ scope。$ watch在范围内注册一个新的观察者。每当有摘要周期时,监视功能就会运行。
$scope.$apply
triggers a digest cycle--that is to say, if nothing ever called $scope.$apply
, no watchers would ever be run at all.
$ scope。$ apply触发一个摘要周期 - 也就是说,如果什么都没有调用$ scope。$ apply,那么根本就不会运行任何观察者。
For built-in directives that deal with user input (ng-click
, ng-keydown
, etc.) and built-in services ($http
, $location
, $timeout
, etc.), Angular calls $scope.$watch
for you. However, any time you deal with asynchronous code that lives outside of these built-in directives or services, you must tell Angular that it should kick off a new digest cycle by calling $apply
yourself.
对于处理用户输入(ng-click,ng-keydown等)和内置服务($ http,$ location,$ timeout等)的内置指令,Angular调用$ scope。$ watch for you 。但是,每当您处理生活在这些内置指令或服务之外的异步代码时,您必须告诉Angular它应该通过自己调用$ apply来启动新的摘要周期。
As mentioned by Stewie, you should try to keep your $apply
calls as close to the asynchronous operation as possible; in this case, it means using it at the very top level of the onload
callback.
正如Stewie所提到的,你应该尽量让你的$ apply调用尽可能接近异步操作;在这种情况下,它意味着在onload回调的最顶层使用它。
#3
0
The only reason i see this happen if xlsxParser.parse(file).then is not a angular promise callback method.
如果xlsxParser.parse(file).then不是角度承诺回调方法,我发现这种情况的唯一原因。
And as confirmed by @Sander this indeed is not a angular promise, so option here is to keep using the existing $scope.$apply call.
正如@Sander所证实的那样,这确实不是一个有角度的承诺,所以这里的选择是继续使用现有的$ scope。$ apply call。
#1
2
It doesn't matter that you're using $scope.$watch. That doesn't help when you're calling $scope.parseFile
from inside reader.onload
callback, which is outside of Angular realm.
你使用$ scope并不重要。$ watch。当你从reader.onload回调中调用$ scope.parseFile时,这无效,这是在Angular领域之外。
$scope.$apply
should be used inside the callback itself:
$ scope。$ apply应该在回调本身内部使用:
reader.onload = function(event) {
$scope.$apply(function(){
$scope.parseFile(newVal);
});
};
#2
0
$scope.$watch
and $scope.$apply
are complementary.
$ scope。$ watch和$ scope。$ apply是互补的。
$scope.$watch
registers a new watcher on the scope. Whenever there's a digest cycle, the watch function runs.
$ scope。$ watch在范围内注册一个新的观察者。每当有摘要周期时,监视功能就会运行。
$scope.$apply
triggers a digest cycle--that is to say, if nothing ever called $scope.$apply
, no watchers would ever be run at all.
$ scope。$ apply触发一个摘要周期 - 也就是说,如果什么都没有调用$ scope。$ apply,那么根本就不会运行任何观察者。
For built-in directives that deal with user input (ng-click
, ng-keydown
, etc.) and built-in services ($http
, $location
, $timeout
, etc.), Angular calls $scope.$watch
for you. However, any time you deal with asynchronous code that lives outside of these built-in directives or services, you must tell Angular that it should kick off a new digest cycle by calling $apply
yourself.
对于处理用户输入(ng-click,ng-keydown等)和内置服务($ http,$ location,$ timeout等)的内置指令,Angular调用$ scope。$ watch for you 。但是,每当您处理生活在这些内置指令或服务之外的异步代码时,您必须告诉Angular它应该通过自己调用$ apply来启动新的摘要周期。
As mentioned by Stewie, you should try to keep your $apply
calls as close to the asynchronous operation as possible; in this case, it means using it at the very top level of the onload
callback.
正如Stewie所提到的,你应该尽量让你的$ apply调用尽可能接近异步操作;在这种情况下,它意味着在onload回调的最顶层使用它。
#3
0
The only reason i see this happen if xlsxParser.parse(file).then is not a angular promise callback method.
如果xlsxParser.parse(file).then不是角度承诺回调方法,我发现这种情况的唯一原因。
And as confirmed by @Sander this indeed is not a angular promise, so option here is to keep using the existing $scope.$apply call.
正如@Sander所证实的那样,这确实不是一个有角度的承诺,所以这里的选择是继续使用现有的$ scope。$ apply call。