Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Component controller #13742

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions src/ng/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -928,7 +928,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
return this;
};

this.$$componentControllers = createMap();
/**
* @ngdoc method
* @name $compileProvider#component
Expand Down Expand Up @@ -1054,8 +1053,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
*/
this.component = function registerComponent(name, options) {
var controller = options.controller || function() {};
var ident = identifierForController(options.controller) || options.controllerAs || '$ctrl';
this.$$componentControllers[name] = { controller: controller, ident: ident};

function factory($injector) {
function makeInjectable(fn) {
Expand All @@ -1071,7 +1068,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
var template = (!options.template && !options.templateUrl ? '' : options.template);
return {
controller: controller,
controllerAs: ident,
controllerAs: identifierForController(options.controller) || options.controllerAs || '$ctrl',
template: makeInjectable(template),
templateUrl: makeInjectable(options.templateUrl),
transclude: options.transclude,
Expand Down
21 changes: 18 additions & 3 deletions src/ngMock/angular-mocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -2183,10 +2183,25 @@ angular.mock.$ControllerDecorator = ['$delegate', function($delegate) {
*/
angular.mock.$ComponentControllerProvider = ['$compileProvider', function($compileProvider) {
return {
$get: ['$controller', function($controller) {
$get: ['$controller','$injector', function($controller,$injector) {
return function $componentController(componentName, locals, bindings, ident) {
var controllerInfo = $compileProvider.$$componentControllers[componentName];
return $controller(controllerInfo.controller, locals, bindings, ident || controllerInfo.ident);
// get all directives associated to the component name
var directives = $injector.get(componentName + 'Directive');
// look for those directives that are components
var candidateDirectives = directives.filter(function(directiveInfo) {
// components have controller, controllerAs and restrict:'E' compatible
return directiveInfo.controller && directiveInfo.controllerAs && directiveInfo.restrict.indexOf('E') >= 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can just check === 'E' rather than indexOf('E')

});
// check if valid directives found
if (candidateDirectives.length === 0) {
throw new Error('No component found');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should to use $minErr for these errors

}
if (candidateDirectives.length > 1) {
throw new Error('Too many components found');
}
// get the info of the component
var directiveInfo = candidateDirectives[0];
return $controller(directiveInfo.controller, locals, bindings, ident || directiveInfo.controllerAs);
};
}]
};
Expand Down
110 changes: 110 additions & 0 deletions test/ngMock/angular-mocksSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1938,6 +1938,116 @@ describe('ngMock', function() {
expect($scope.testCtrl).toBe(ctrl);
});
});

it('should instantiate the controller of the restrict:\'E\' component if there are more directives with the same name but not \'E\' restrictness', function() {
function TestController() {
this.r = 6779;
}
module(function($compileProvider) {
$compileProvider.directive('test', function() {
return { restrict: 'A' };
});
$compileProvider.component('test', {
controller: TestController
});
});
inject(function($componentController, $rootScope) {
var ctrl = $componentController('test', { $scope: {} });
expect(ctrl).toEqual({ r: 6779 });
});
});

it('should instantiate the controller of the restrict:\'E\' component if there are more directives with the same name and \'E\' restrictness but no controller', function() {
function TestController() {
this.r = 22926;
}
module(function($compileProvider) {
$compileProvider.directive('test', function() {
return { restrict: 'E' };
});
$compileProvider.component('test', {
controller: TestController
});
});
inject(function($componentController, $rootScope) {
var ctrl = $componentController('test', { $scope: {} });
expect(ctrl).toEqual({ r: 22926 });
});
});

it('should instantiate the controller of the directive with controller if there are more directives', function() {
function TestController() {
this.r = 18842;
}
module(function($compileProvider) {
$compileProvider.directive('test', function() {
return { };
});
$compileProvider.directive('test', function() {
return {
controller: TestController,
controllerAs: '$ctrl'
};
});
});
inject(function($componentController, $rootScope) {
var ctrl = $componentController('test', { $scope: {} });
expect(ctrl).toEqual({ r: 18842 });
});
});

it('should fail if there is no directive with restrict:\'E\' compatible and controller', function() {
function TestController() {
this.r = 31145;
}
module(function($compileProvider) {
$compileProvider.directive('test', function() {
return {
restrict: 'AC',
controller: TestController
};
});
$compileProvider.directive('test', function() {
return {
restrict: 'E',
controller: TestController
};
});
$compileProvider.directive('test', function() {
return { restrict: 'E' };
});
});
inject(function($componentController, $rootScope) {
expect(function() {
$componentController('test', { $scope: {} });
}).toThrow('No component found');
});
});

it('should fail if there more than two components with same name', function() {
function TestController($scope, a, b) {
this.$scope = $scope;
this.a = a;
this.b = b;
}
module(function($compileProvider) {
$compileProvider.directive('test', function() {
return {
controller: TestController,
controllerAs: '$ctrl'
};
});
$compileProvider.component('test', {
controller: TestController
});
});
inject(function($componentController, $rootScope) {
expect(function() {
var $scope = {};
$componentController('test', { $scope: $scope, a: 'A', b: 'B' }, { x: 'X', y: 'Y' });
}).toThrow('Too many components found');
});
});
});
});

Expand Down