2015-09-30 2 views
0

У меня есть директива, которая обрабатывает загрузку файлов. Директива использует «контроллер» и «controllerAs» для динамических контроллеров, а в функции «link» она вызывает обратные вызовы, которые запускаются в соответствующем динамическом контроллере.«это» не определено в обратном вызове из директивы

проблема, когда обратный вызов выполняется в контроллере, «это» не определено. Как установить 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 's ответ разрешает ошибку' undefined ', но почему imageURL's новое значение недоступно вне моего контроллера, т. е. вид?

обновленный контроллер:

... 
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> 

ответ

0

Угловое установит this из $timeout к окну.

У вас есть несколько вариантов. Или:

Свяжите этот контекст вашей функции:

this.test = 'hiya'; 

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

Или с помощью угловой v1.4.1 или выше

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

см скрипку: http://jsfiddle.net/wopx3rtc/1/

+0

Ваше предложение разрешает 'undefined', но проверьте мой отредактированный вопрос pls - новое значение imageURL не отражает в моем представлении. Какие-либо предложения? – ceebreenk

+0

, потому что вы используете 'this' и' controllerAs', вам не нужно ссылаться на него в своем представлении с помощью 'uploadCtrl.imageURL'? Я никогда не делал этого в директивах, но это то, как это работает с 'ng-controller'. Если вы хотите использовать синтаксис, который вы получили в своем представлении, сбрасывайте контроллер и заменяете 'this' своей' $ scope'. – ste2425

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); 
    }; 
    .... 
Смежные вопросы