在指令

时间:2015-09-30 10:32:49

标签: angularjs

我有一个处理文件上传的指令。该指令使用'controller'和'controllerAs'作为动态控制器,在'link'函数中,它触发在相关动态控制器中执行的回调。

问题是在控制器中执行回调时,'this'未定义。如何在控制器中设置imageUrl?

指令:

.directive('attachable', function(FileUploader) {
return {
  restrict    : 'E',
  transclude  : true,
  templateUrl : 'template.html',
  scope       : {},
  controller  : '@',
  controllerAs: 'uploadCtrl',
  name        : 'controller', 

  link: function(scope, element, attrs) {

      var controller = scope.uploadCtrl;

      var uploader = scope.uploader = new FileUploader({
          url: controller.uploadUrl
      });

      // callbacks
      uploader.onAfterAddingFile = function(item) {
            controller.onAfterAddSuccess();
      };
   }
  };
});

控制器:

angular.module('core').controller('controller', ['$window', function($window){

    this.onAfterAddSuccess = function(item){

        if ($window.FileReader) {
            var fileReader = new FileReader();
            fileReader.readAsDataURL(item._file);

            fileReader.onload = function (fileReaderEvent) {
                $timeout(function () {
                    this.imageURL = fileReaderEvent.target.result;  // <- this is undefined
                }, 0);
            };
        }
    };
}]);        

HTML:

<attachable controller="controller" ></attachable>  

修改

ste2425的答案解决了'未定义'的错误,但为什么 imageURL的新值在我的控制器外不可用,即视图?

更新控制器:

...
fileReader.onload = function (fileReaderEvent) {

    this.imageURL = '';
    $timeout(function(){
        this.imageURL = fileReaderEvent.target.result;
    }.bind(this), 1);
};
...

HTML:

imageURL: {{ imageURL }}     <- this is still ''
<attachable controller="controller" ></attachable>  

2 个答案:

答案 0 :(得分:0)

Angular会将this的{​​{1}}设置为窗口。

您有几种选择。之一:

绑定你的函数的这个上下文:

$timeout

或使用角度v1.4.1或更高

    this.test = 'hiya';

   $timeout(function(){
        console.log('this WONT fail', this.test);
    }.bind(this), 1);

请参阅小提琴:http://jsfiddle.net/wopx3rtc/1/

答案 1 :(得分:0)

这是JavaScript闭包的副作用。解决此问题的最常用,直接的方法是声明一个表示控制器的常量变量,该变量可以在闭包内引用,而不会被闭包本身隐藏。

angular.module('core').controller('controller', ['$window', function($window){
  var vm=this; //constant reference to controller
  ....
  fileReader.onload = function (fileReaderEvent) {
    vm.imageURL = '';
    $timeout(function(){
      vm.imageURL = fileReaderEvent.target.result;
    }, 0);
  };
  ....