daniel
daniel

Reputation: 35683

Call controller function when directive attribute changed

My code so far:

 .directive('ngSpreadsheet', function () {
      return {
          restrict: 'EA',
          scope: {
              curpart: '='
          },
          template: '<div id="dataTable" class="dataTable"></div>',
          controller: SpreadsheetController,
          link: function (scope, element, attrs) { 
              scope.$watch('curpart', function (val) {
                  console.log('curpart value changed, new value is: ' + val);
                  // here i want to call a function of the SpreadsheetController 
                  // or is there a better way, executing stuff when an attribute changed?
              });
          }

      }
  })


var SpreadsheetController = (function () {
  ...

  SpreadsheetController.prototype.curPartChanged = function () {
        console.debug('curPartChanged');
    };
})();

Upvotes: 0

Views: 2292

Answers (3)

Patrick
Patrick

Reputation: 6948

If you want to get reference to your controller in your directive, then require your own directive. See: http://jsfiddle.net/7LnrZ/22/

var mod = angular.module("myapp", []);

mod.controller("SimpleCtrl", function ($scope) {
    var part = {};
    part.curpart = 1;

    $scope.part = part;

    $scope.increasePart = function () {
        part.curpart++;   
    }
});

var SpreadsheetController = function () {
    console.log("Instantiating SpreadsheetController");    
}

SpreadsheetController.prototype.curPartChanged = function () {
    console.log('curPartChanged');
}

mod.directive("ngSpreadsheet", function ($window) {
    return {
        restrict: 'EA',
        scope: {
            curpart: '='
        },
        require: "ngSpreadsheet",
        template: '<div id="dataTable" class="dataTable"></div>',
        controller: SpreadsheetController,
        link: function (scope, element, attrs, ctrl) { 
            scope.$watch('curpart', function (val) {
                console.log('curpart value changed, new value is: ' + val);
                ctrl.curPartChanged();
              });
          }
    }
});

Compiling order for a directive:

  • Directive Controller is called/created
  • Directive pre-link function is invoked
    • Child directive(s) of directive controller is created
    • Child directive(s) of directive pre-link is invoked
    • Child directive(s) of directive post-link is invoked
  • Directive post-link function is invoked

Upvotes: 1

Hylianpuffball
Hylianpuffball

Reputation: 1561

The fourth parameter to a link function is the controller; I would recommend getting access that way.

link: function (scope, element, attrs, controller){
    //...
    controller.curPartChanged(...);
    //...
}

I can't seem to link directly to the anchor, but look in this doc for the section on LINK. You can search for "A controller instance if at least one directive on the element defines a controller" to find the exact section.

EDIT:

If you'd like to watch an attribute of a directive, I would consider the $observe function, which is very similar to $watch. Head to this SO post to learn more.

Upvotes: 1

Nemesarial
Nemesarial

Reputation: 507

Communication between a directive and the controller that hosts it should happen via an event call. scope.$emit will send such an event, while $scope.$on will catch events on the other side.

.directive('ngSpreadsheet', function () {
    return {
        restrict: 'EA',
        scope: {
            curpart: '='
        },
        template: '<div id="dataTable" class="dataTable"></div>',

        controller: function($scope){
            $scope.$on('curpart.change',function(data){
            console.log('curpart changed.. the new value is: ',data);
        }),

        link: function (scope, element, attrs) { 
            scope.$watch('curpart', function (evt,val) {
                console.log('curpart value changed, new value is: ' + val);
                scope.$emit('curpart.change',val);
            });
        }        
    }
});

Upvotes: 0

Related Questions