Reputation: 1436
I have an application which has two directives, where one directive requires the other. I have replicated it to mirror the base of the application:
var module = angular.module('testApp', ['testApp.directiveA', 'testApp.directiveB']);
// Here goes your modules definition
module.controller('AppCtrl', function ($scope, $log) {
});
angular.module('testApp.directiveA', ['testApp.directiveB'])
.directive('directiveA', function () {
return {
restrict: 'EA',
require: '^directiveB',
template: '<div><h1>DirectiveA</h1></div>',
scope: {
value: "@"
},
link: function (scope, element, attrs, directiveBCtrl) {
scope.testFunction = function() {
return directiveBCtrl.exampleFunction();
};
scope.value = scope.testFunction();
}
}
});
angular.module('testApp.directiveB', [])
.directive('directiveB', function () {
return {
restrict: 'EA',
template: '<div><h1>DirectiveB</h1></div>',
scope: {
value: "@"
},
controller: function ($scope) {
$scope.exampleFunction = function() {
return true;
};
}
}
});
I am trying to write a test using Jasmine to test different functions in directiveA:
describe('Test directive with require', function () {
var $scope, elem, scope;
beforeEach(angular.mock.module("testApp.directiveA", "testApp.directiveB"));
beforeEach(inject(function ($rootScope, $compile) {
elem = angular.element('<directive-a value="aValue"></directive-a>');
$scope = $rootScope.$new();
$compile(elem)($scope);
$scope.$digest();
scope = elem.isolateScope();
}));
it('Should test a function on directiveA', function() {
var result = scope.testFunction();
expect(result).toEqual(true);
});
});
When I run this, I get the error:
Controller 'directiveB', required by directive 'directiveA', can't be found!
I have setup A Plnkr which reproduces the error. I cannot seem to figure out how I can inject one directive, or rather its controller, into the other directive. Any help is greatly appreciate.
http://plnkr.co/edit/pKDNkiO1ZHxE6qQKXXF5?p=preview
Upvotes: 0
Views: 1132
Reputation: 3188
Here's an updated jasmine beforeEach
code (or plunker):
beforeEach(inject(function($rootScope, $compile) {
elem = angular.element('<directive-b><directive-a value="aValue"></directive-a></directive-b>');
$scope = $rootScope.$new();
$compile(elem)($scope);
$scope.$digest();
scope = elem.children(':first').isolateScope();
}));
And updated directiveB code:
directive('directiveB', function() {
return {
restrict: 'EA',
//template: '<div><h1>DirectiveB</h1></div>',
scope: {
value: "@"
},
controller: function($scope) {
this.exampleFunction = function() {
return true;
};
}
}
});
Takeaway:
elem.children(':first').isolateScope()
this
to create controller methods instead of $scope
UPD:
You can use transclude if your parent directive needs to have a template. Here is a pluker.
Upvotes: 1