4

In AngularJS there are two styles of writing controllers, the "the controller as syntax" and the "'attach to $scope' style of controller" (both quotes from the ngController documentation.) There are several questions on StackOverflow comparing these styles, for example this vs $scope in AngularJS controllers and Performance differences between controller functions defined on $scope or this - AngularJS.

I have a method on a controller which needs to prompt AngularJS after a model update. Using the $scope style of controller I can do that thus:

myApp.controller('MainController', ['$scope', function($scope) {
    $scope.content = "[Waiting for File]";
    $scope.showFileContent = function(fileContent) {
        $scope.content = fileContent;
        $scope.$apply();
    };
}]);

But if I write the controller using 'this'

myApp.controller('MainController', function () {
    this.content = "[Waiting for File]";
    this.showFileContent = function(fileContent){
        this.content = fileContent;
    };
});

how do I invoke $apply()?

br.julien
  • 3,420
  • 2
  • 23
  • 44
dumbledad
  • 16,305
  • 23
  • 120
  • 273
  • You can get around using `$apply` by wrapping your async task with `$q`. Have you considered that? – Yoshi Dec 15 '14 at 18:24

1 Answers1

4

If you really need $scope, you still can inject it. Assuming "controller as" syntax:

myApp.controller('MainController', function($scope) {
   this.content = "[Waiting for File]";
   $scope.$apply(); // etc.
});

The question is, do you really need to run $scope.$apply() there? Assuming you are using it properly in "controller as" syntax, it should see it:

<div ng-controller="MainController as main">
  <div id="content">{{main.content}}</div>
</div>

Then div#content will be updated when you update your this.content var. Mind you, you need to be careful of how you use this, so you might need:

myApp.controller('MainController', function($scope) {
   var that = this;
   this.content = "[Waiting for File]";
   this.showFileContent = function(fileContent){
       // 'this' might not be set properly inside your callback, depending on how it is called.
       // main.showFileContent() will work fine, but something else might not
       that.content = fileContent;
   };
});
deitch
  • 14,019
  • 14
  • 68
  • 96
  • Thanks @deitch. I was not expecting to need to use `$source.$apply()` either, but [my html is not re-rendering without it](http://stackoverflow.com/questions/27489485/simple-mixture-of-javascript-and-angularjs-not-displaying-file-contents). – dumbledad Dec 15 '14 at 18:12
  • Oh, I see! You are calling `showFileContent()` in response to a `FileReader` event, so the callback is executed outside of the Angular context. Is that it? – deitch Dec 15 '14 at 18:32
  • Yeah, also your `onchange` executes stuff outside the Angular context. I will comment on there. It is a separate question. – deitch Dec 15 '14 at 18:34