Reputation: 7050
I'm stumped with a rather simple issue with Angular (as I think it is simple). Sometimes Angular make me feel dumb, because it can't be possible I'm doing something terrible wrong.
Take this plnkr http://plnkr.co/edit/BmM9C5zjDAIfGTVzkU29?p=preview
HTML:
<body ng-app="app">
<div ng-controller="ASDF">
<div fb-login="doh" ng-click="exec()">CLICKY (should execute parent scope function but doesnt)</div>
</div>
</body>
Javascript:
angular.module('app', [])
.controller('ASDF', function($scope){
$scope.doh = function(d){
alert(d);
}
})
.directive('fbLogin', function(){
return {
restrict: 'A',
replace: false,
scope: {
done: '&fbLogin'
},
link: function(scope){
scope.exec = function(){
scope.done()('asdf');
};
}
}
});
What's going on in here?
Upvotes: 1
Views: 1830
Reputation: 7050
Isolate scope in 1.2 versions are trully isolate (see https://github.com/angular/angular.js/commit/909cabd36d779598763cc358979ecd85bb40d4d7)
fix($compile): make isolate scope truly isolate
Fixes issue with isolate scope leaking all over the place into other directives on the same element.
Isolate scope is now available only to the isolate directive that requested it and its template.
A non-isolate directive should not get the isolate scope of an isolate directive on the same element, instead they will receive the original scope (which is the parent scope of the newly created isolate scope).
Paired with Tobias.
BREAKING CHANGE: Directives without isolate scope do not get the isolate scope from an isolate directive on the same element. If your code depends on this behavior (non-isolate directive needs to access state from within the isolate scope), change the isolate directive to use scope locals to pass these explicitly.
// before
.directive('ngIsolate', function() { return { scope: {}, template: '{{value}}' }; });
// after
.directive('ngIsolate', function() { return { scope: {value: '=ngModel'}, template: '{{value}} }; });
Then only way it works now is through a template / templateUrl (using transclude in this case, so I don't need to recreate it):
angular.module('app', [])
.controller('ASDF', function($scope){
$scope.doh = function(d){
alert(d);
}
})
.directive('fbLogin', function(){
return {
restrict: 'A',
replace: false,
scope: {
done: '&fbLogin'
},
transclude: true,
template: '<div ng-transclude ng-click="exec()"></div>',
link: function(scope){
scope.exec = function(){
scope.done()('asdf');
};
}
}
});
Upvotes: 2
Reputation: 617
Because the ng-click is only going to have access to the parent scope, it is trying to execute exec on the scope of the ASDF controller.
I believe this will give you the behavior you want:
HTML:
<body ng-app="app">
<div ng-controller="ASDF">
<div fb-login="doh">CLICKY (should execute parent scope function but doesnt)</div>
</div>
</body>
Javascript:
angular.module('app', [])
.controller('ASDF', function($scope){
$scope.doh = function(d){
alert(d);
}
})
.directive('fbLogin', function(){
return {
restrict: 'A',
replace: false,
scope: {
done: '&fbLogin'
},
link: function(scope, element){
element.on("click", function () { scope.done()('asdf') });
}
}
});
Upvotes: 1