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'
  };
}

      

+3


source to share


2 answers


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

.

0


source


In $ watch, try using the watchcher function like this:



$scope.$watch(function() {
  return $scope.window.x
 }, ...

      

0


source







All Articles