Sharing scope between controller & directive in AngularJS

angularjs, angularjs-directive, angularjs-scope

Solution

There are a number of scope issues at work in your demo. First , within the `dateChange` callback, even though the function itself is declared inside the controller, the context of `this` within the callback is the bootstrap element since it is within a bootstrap handler.

Whenever you change angular scope values from within third party code , angular needs to know about it by using `$apply`. Generally best to keep all third party scopes inside the directive.

A more angular apprroach is to use `ng-model` on the input. Then use `$.watch` for changes to the model. This helps keep all the code inside the controller within angular context. Is rare in any angular application not to use `ng-model` on any form controls

 <input type="text"  class="datepicker" datepicker="" ng-model="myDate">

Within directive:

dateInput.bind('changeDate',function(){
      scope.$apply(function(){
         scope[attrs.ngModel] = element.val()
      });
});

Then in Controller:

$scope.$watch('myDate',function(oldVal,newVal){ 
       if(oldVal !=newVal){
           /* since this code is in angular context will work for the hide/show now*/
            $scope.dateChanged=true;
             $timeout(function(){
                   $scope.dateChanged=false;
              },5000);
        }        
});

Demo: http://jsfiddle.net/qxjck/10/

EDIT One more item that should change is remove `var dateInput = angular.element('.datepicker')` if you want to use this directive on more than one element in page. It is redundant being used in directive where `element` is one of the arguments in the `link` callback already, and is instance specific. Replace `dateInput` with `element`

Problem

I've created a directive to wrap a jQuery plugin, and I pass a config object for the plugin from the controller to the directive. (works) In the config object is a callback that I want to call on an event. (works) In the callback, I want to modify a property on the controller's $scope, which does not work. Angular does not recognize that the property has changed for some reason, which leads me to believe that the $scope in the callback is different than the controller's $scope. My problem is I just don't why. Can anybody point me in the right direction? Click here for Fiddle app.js ``` var app = angular.module('app', []) .directive('datepicker', function () { return { restrict: 'A', link: function (scope, element, attrs) { // Uncommenting the line below causes // the "date changed!" text to appear, // as I expect it would. // scope.dateChanged = true; var dateInput = angular.element('.datepicker') dateInput.datepicker(scope.datepickerOpts); // The datepicker fires a changeDate event // when a date is chosen. I want to execute the // callback defined in a controller. // --- // PROBLEM: // Angular does not recognize that $scope.dateChanged // is changed in the callback. The view does not update. dateInput.bind('changeDate', scope.onDateChange); } }; }); var myModule = angular.module('myModule', ['app']) .controller('MyCtrl', ['$scope', function ($scope) { $scope.dateChanged = false; $scope.datepickerOpts = { autoclose: true, format: 'mm-dd-yyyy' }; $scope.onDateChange = function () { alert('onDateChange called!'); // ------------------ // PROBLEM AREA: // This doesnt cause the "date changed!" text to show. // ------------------ $scope.dateChanged = true; setTimeout(function () { $scope.dateChanged = false; }, 5000); }; }]); ``` html ``` <div ng-controller="MyCtrl"> <p ng-show="dateChanged">date changed!</p> <input type="text" value="02-16-2012" class="datepicker" datepicker=""> </div> ```

Original source