8

I'm developing a dashboard with sortable, dockable, floatable widgets. One of the controls I'm using generates the floating widgets as HTML at the bottom of the DOM, before the closing body tag. This effectively removes actions done in the window controls from the controller scope they are generated in.

I'm developing this dashboard controller using controllerAs syntax available, but I can't figure out how to effectively update the view with this syntax when an external component does an action that affects the data for the view?

Note: This is not the only I'm facing that forces me to manually update the main view. There are also directives elsewhere on the page that perform actions that impact the view.

Ideally, I would never have to update the view manually, because I would be using all commands that happen within the built in Angular commands affecting digest loop - but this was not an option for me.

So... if I was using $scope I would be able to simply do:

$scope.$digest

Or

$scope.$apply

But how do I achieve the same affect using controller as?

var vm = this;
vm.array = [item, item];
vm.something = something;

//External something changes something on a vm.variable

vm.update! //How??

2 Answers 2

7

With 'as' you are defining the way you will refer to your controller scope in you view.

So this:

<body ng-controller="MainCtrl">
  <p>Hello {{name}}!</p>
</body>

app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';
});

Is equal to this:

<body ng-controller="MainCtrl as main">
  <p>Hello {{main.name}}!</p>
</body>

Your controller:

app.controller('MainCtrl', function($scope) {
  this.name = 'World';
});

DEMO

So basically you should be able to call this.$digest or this.$apply as you would do on $scope.

UPDATE

After doing some search, I think the correct solution should be using $scope.apply() or $scope.digest().

Main resource:
AngularJS’s Controller As and the vm Variable
There is a comment rising your same question and the author replay:

You can use $scope.$apply() in that case and just inject $scope for that purpose (still using vm for everything else). However, if you switch fro using ajax to using Angular's $http, then you won't need to call $apply as angular's $http does that for you. That's what I recommend

Other resources I found:

Sign up to request clarification or add additional context in comments.

5 Comments

Using var vm = this; and then vm.$digest(); causes an error: Object doesn't support property or method '$digest'.
I think you need to use $scope.$digest() or $scope.$apply() in this case. Have a look at this article where it explains about $scope injection
I've read that article before and I think it specifically mentions $scope injection in reference to watches or broadcasts, which makes me think there may be a way to apply updates without scope. There <i>should</i> be anyway.
this is not equal to $scope, so I still think that the right solution is $scope.$apply(), but since I am not 100% sure, I'll wait for other replies. I also add a couple of link to my answer to help investigate.
When using controllerAs, you must inject the $scope itself to the controller function. Then you can use normally $scope.$apply() etc
0

Try to do your update in $scope.$apply block like this:

$scope.apply(function() {
    vm.something = some_new_value;
});

To avoid "Digest already in progress" error, wrap that in $timeout

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.