Reputation: 59213
I have a controller like this:
angular.module('main', []).controller('mainCtrl', function ($scope) {
$scope.doStuff = function (cb) {
// Do some stuff.
cb();
};
});
And I have a directive like this:
angular.module('action-bar', []).directive('actionBar', function () {
return {
restrict: 'EA',
replace: true,
template: '<h1>test</h1>',
scope: {
doStuff: '&'
},
link: function (scope, element, attrs) {
scope.doStuff(function () {
alert('callback executed');
});
}
};
});
Here is the markup:
<div ng-app="main">
<div ng-controller="mainCtrl">
<div ng-action-bar></div>
</div>
</div>
I can call doStuff
just fine, however the cb
argument is always undefined
even though I'm passing in an anonymous function as the callback. What am I doing wrong here?
Upvotes: 0
Views: 215
Reputation: 59213
I solved this by simply using scope.$parent
to access the parent scope. I don't actually need the parent function to be part of the directive's isolate scope.
Example:
var app = angular.module('app', []);
// Main controller.
app.controller('mainCtrl', function ($scope) {
// Initial text added to log.
$scope.logs = ['App loaded.'];
// A log function to add additional lines to the log.
$scope.log = function (text, callback) {
$scope.logs.push(text);
if (callback) callback();
};
});
// Directive to log lines to the log viewer.
app.directive('ngLogLine', function () {
return {
restrict: 'E',
template: '<div><input type="text" ng-model="msg" ng-keydown="$event.keyCode === 13 ? log() : null" /><button ng-click="log()">send</button></div>',
replace: true,
scope: {},
link: function (scope, element, attrs) {
// Create our own log function on our isolate scope.
scope.log = function () {
// Call parent log function and pass in a callback.
scope.$parent.log(scope.msg, function () {
// Clear the msg, clearing the input.
scope.msg = '';
});
};
}
};
});
Codepen: http://codepen.io/Chevex/pen/eHuaK/
Upvotes: 0
Reputation: 18513
If you want to use the expression ('&') syntax for passing doStuff into your directive then in your html you should pass it in like this:
<div action-bar doStuff="doStuff(cb)"></div>
and in your directive's link function you can call it like this:
scope.doStuff({cb: function() { ... }});
Checkout the egghead.io video on it for more info: https://egghead.io/lessons/angularjs-isolate-scope-expression-binding
Note: I personally don't like this syntax so I always use Jonathan Palumbo's solution (two way binding).
Upvotes: 0
Reputation: 6871
Changing your isolate scope to use =
instead of &
allows you to access the parent scopes doStuff method.
angular.module('main', ['action-bar']).controller('mainCtrl', function ($scope) {
$scope.doStuff = function (cb) {
// Do some stuff.
cb();
};
});
angular.module('action-bar', []).directive('actionBar', function () {
return {
restrict: 'EA',
replace: true,
template: '<h1>test</h1>',
scope: {
doStuff: '='
},
link: function (scope, element, attrs) {
scope.doStuff(function () {
alert('callback executed');
});
}
};
});
Using the directive in you markup
<div ng-app="main" ng-controller="mainCtrl">
<action-bar do-stuff="doStuff">
</action-bar>
</div>
Here is a working example.
Upvotes: 2