Viewing controller properties from directive in Angular
I am trying to view the properties of a controller from its associated directive from a link function. The controller itself is set to the "window" object on the $ scope using controllerAs; here is the definition of the directive:
function windowDirective() {
return {
transclude: true,
template: template,
restrict: 'E',
controller: WindowCtrl,
controllerAs: 'window',
link: function($scope, $element, $attrs, $ctrl) {
$scope.$watch('window.x', function(newValue, oldValue) {
// access x here
});
}
};
}
And here is WindowCtrl
'use strict';
class WindowCtrl {
move(x, y) {
this.x = x;
this.y = y;
}
}
module.exports = WindowCtrl;
move(x, y)
is called when a child directive is dragged - it is definitely called and this.x
and is this.y
definitely set in WindowCtrl. Also, if I console.dir
$scope
then fire move()
several times, I can open scope in chrome (because she lazily evaluated) and see that $scope.window.x
and $scope.window.y
are actually installed.
However mine $scope.$watch
never fires aside when it initially detects that it window.x
is undefined. Not really sure how to proceed. I did a search and tried all the solutions I found, but none of them seemed to work.
I am using Angular 1.3.16.
NB: access WindowCtrl.move()
only comes from the Angular digest loop - see below - however using $scope.$apply()
solves this. I don't know why this is so. Can you explain? Below is the directive nested inside the said directive. It will call the method in onDrag
, which in my example points towindow.move(x, y);
function windowHeaderDirective() {
return {
transclude: true,
template: template,
replace: true,
require: `^${windowDirective.$name}`,
scope: {
enableClose: '=actionClose',
draggable: '=',
onDrag: '&'
},
bindToController: true,
link: function($scope, $element, $attrs, $ctrl) {
$scope.close = $ctrl.close.bind($ctrl);
let moving = false;
$element.on('mousemove', function(event) {
if(!moving) return
const { x, y } = event;
$scope.header.onDrag({ x, y });
// $scope.$apply here will fix this issue, but why? Isn't $element.on within angular digest cycle??
});
$element.on('mousedown', function(event) {
moving = true;
});
$element.on('mouseup', function(event) {
moving = false
});
},
controller: controller,
controllerAs: 'header'
};
}
source to share
Auto Answer:
It seems due to my update I answered the question myself, so
$element.on
is apparently not in the angular digest loop - this is pretty unexpected to me, I assumed it would. However, this essentially means that my code is working as it should - it's just that the variable changes on the controller don't immediately show up. The way to fix this is simply to use either ng-mousedown
et al or $scope.$apply
in a handler $element.on
.
source to share