簡體   English   中英

在角度工廠中訪問范圍

[英]Accessing scope in angular factory

要求是單擊按鈕后顯示成功消息。由於必須在許多控制器中使用此成功消息,因此我決定使用服務來執行此操作。 但是我無法進入范圍

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);
            }
        } 
});

我收到以下錯誤, 無法讀取未定義的屬性“ displayMsgService”

我錯過了什么

打字機

$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)


但是, 將控制器$ scope傳遞給工廠/服務不是一個好習慣 :請參閱以下文章:將當前范圍傳遞給AngularJS服務並將范圍注入服務

為避免將范圍傳遞給服務,這里有兩種解決方案:


1.廣播

在您的情況下,最簡單的方法是從服務中廣播事件,以使您的控制器知道文件已上傳,如下所示:

 $rootScope.$broadcast('uploadDone');

注意:同樣, $rootScope需要在服務/工廠中注入

並在您的控制器中:

$scope.$on('uploadDone',function(){
 //modify $scope here
}

2.承諾

對於上傳等異步事件,您也可以考慮使用Promise。 即使它們不像廣播那樣簡單,但在這種情況下,它們仍是標准做法。

在您的控制器中:

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中使用promise的更多信息:

將$ q與angularjs一起使用的官方文檔

思想家學費

您可以嘗試使用基本控制器代替服務。

基本控制器

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();
  };
}]);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM