feat(directive): support as instance syntax

Support controller: 'MyController as my' syntax for directives which publishes
the controller instance to the directive scope.

Support controllerAs syntax to define an alias to the controller within the
directive scope.
This commit is contained in:
Lucas Galfasó 2013-05-24 21:18:51 -03:00 committed by Misko Hevery
parent aa5a16224b
commit b3777f275c
3 changed files with 64 additions and 2 deletions

View file

@ -401,6 +401,13 @@ compiler}. The attributes are:
* `^` - Locate the required controller by searching the element's parents.
* `?^` - Attempt to locate the required controller by searching the element's parents, or return `null` if not found.
* `controllerAs` - Controller alias at the directive scope. An alias for the controller so it
can be referenced at the directive template. The directive needs to define a scope for this
configuration to be used. Useful in the case when directive is used as component.
* `require` - Require another controller be passed into current directive linking function. The
`require` takes a name of the directive controller to pass in. If no such controller can be
found an error is raised. The name can be prefixed with:
* `restrict` - String of subset of `EACM` which restricts the directive to a specific directive
declaration style. If omitted, the default (attributes only) is used.

View file

@ -961,16 +961,25 @@ function $CompileProvider($provide) {
$element: $element,
$attrs: attrs,
$transclude: boundTranscludeFn
};
}, controllerInstance;
controller = directive.controller;
if (controller == '@') {
controller = attrs[directive.name];
}
controllerInstance = $controller(controller, locals);
$element.data(
'$' + directive.name + 'Controller',
$controller(controller, locals));
controllerInstance);
if (directive.controllerAs) {
if (typeof locals.$scope !== 'object') {
throw new Error('Can not export controller as "' + identifier + '". ' +
'No scope object provided!');
}
locals.$scope[directive.controllerAs] = controllerInstance;
}
});
}

View file

@ -2244,6 +2244,52 @@ describe('$compile', function() {
});
iit('should support controllerAs', function() {
module(function() {
directive('main', function() {
return {
templateUrl: 'main.html',
transclude: true,
scope: {},
controller: function() {
this.name = 'lucas';
},
controllerAs: 'mainCtrl'
};
});
});
inject(function($templateCache, $compile, $rootScope) {
$templateCache.put('main.html', '<span>template:{{mainCtrl.name}} <div ng-transclude></div></span>');
element = $compile('<div main>transclude:{{mainCtrl.name}}</div>')($rootScope);
$rootScope.$apply();
expect(element.text()).toBe('template:lucas transclude:');
});
});
it('should support controller alias', function() {
module(function($controllerProvider) {
$controllerProvider.register('MainCtrl', function() {
this.name = 'lucas';
});
directive('main', function() {
return {
templateUrl: 'main.html',
scope: {},
controller: 'MainCtrl as mainCtrl'
};
});
});
inject(function($templateCache, $compile, $rootScope) {
$templateCache.put('main.html', '<span>{{mainCtrl.name}}</span>');
element = $compile('<div main></div>')($rootScope);
$rootScope.$apply();
expect(element.text()).toBe('lucas');
});
});
it('should require controller on parent element',function() {
module(function() {
directive('main', function(log) {