要求是在点击按钮后显示成功消息。由于必须在许多控制器上使用,我决定使用服务来执行相同操作。 但我无法访问范围
的index.html
<div ng-controller="uploadController">
<div class="col-md-6" ng-click="uploadFile()" >
<div class="form-group has-success" id="divsubmitbtn">
<button type="submit" id="submit" class="btn btn-custom"
ng-click="submitData()" ng-disabled="isDisableSubmit">
<span class="glyphicon glyphicon-upload"></span> Upload</button>
</div>
</div>
<div class=" col-md-12">
<div ng-show="showError" ng-class="{fade:doFade}" class="alert alert- success">
<strong>Success:</strong> {{successMessage}}
</div>
</div>
</div>
controller.js
app.controller('uploadController', ['$scope','$timeout','$rootScope','displayMsgService',function($scope,$timeout,$rootScope,displayMsgService) {
$scope.uploadFile = function($scope,displayMsgService){
$scope.displayMsgService.show();
};
$rootScope.submitData = function() {
$scope.uploadFile();
};
}]);
service.js
app.factory('displayMsgService',function() {
return {
show : function($scope){
$scope.showError = false;
$scope.doFade = false;
$scope.showError = true;
$scope.successMessage = "success";
$timeout(function(){
$scope.doFade = true;
}, 2500);
}
}
});
我收到以下错误 无法读取属性&#39; displayMsgService&#39;未定义的
我错过了什么
答案 0 :(得分:3)
错字
$rootScope.submitData = function() {
$scope.uploadFile();
};
我认为你的意思是:$scope.submitData
,因为submitData
是控制器中的$ scope方法;
和$scope.displayMsgService.show();
应该是displayMsgService.show();
,因为displayMsgService
是注入的服务,与$ scope无关(不是控制器范围方法)
在您的控制器中,尝试:
$scope.uploadFile = function($scope,displayMsgService){
displayMsgService.show($scope);
};
编写工厂函数的方式,必须通过控制器范围;如果您从工厂修改范围,您还需要致电$scope.$apply()
;
说明
show : function($scope)
并不意味着范围被注入您的工厂方法。相反,它意味着show函数必须传递一个参数;您可以将show : function($scope)
替换为show : function(arg)
并获得相同的结果。
这就是您必须从控制器传递范围的原因:displayMsgService.show($scope)
但是,将您的控制器$范围传递给工厂/服务并非良好做法:请参阅以下帖子:Passing current scope to an AngularJS Service和injecting scope into a service
为了避免将范围传递给服务,这里有两个解决方案:
在您的情况下,最简单的方法是从您的服务广播一个事件,让您的控制器知道该文件已上传,如下所示:
$rootScope.$broadcast('uploadDone');
注意:同样,$rootScope
需要在服务/工厂中注入
并在您的控制器中:
$scope.$on('uploadDone',function(){
//modify $scope here
}
对于像上传这样的异步事件,您还可以考虑使用promises。虽然它们不像广播那么简单,但在这种情况下它们是标准做法。
在您的控制器中:
uploadMsgService.upload()
.then(function{
//do something to $scope
});
并在您的服务中:
app.factory('uploadMsgService',function($q) {
var deferred = $q.defer();
doTheUpload(inputData,function(err,data){
if(err){deferred.reject("there was an error:"+err);}
deferred.resolve(data);
})
return deferred.promise;
});
有关使用angularjs的承诺的更多信息:
答案 1 :(得分:1)
您可以尝试使用基本控制器代替服务。
基本控制器
app.controller('DisplayMsgController', ['$scope', function ($scope) {
$scope.show = function () {
// Set all your required variables and messages here
};
}]);
然后您只需将基本控制器包含在您想要所需功能的任何控制器中。
上传控制器
app.controller('UploadController', ['$scope', '$controller', function ($scope, $controller) {
// Pass the scope to the controller
$controller('DisplayMsgController', { $scope: $scope });
// Do your processing of data and then call the DisplayMsgController's function
// As you would any other function in the current controller
$scope.uploadFile = function(){
// Do processing here
...
// Display message
$scope.show();
};
}]);