2015-09-27 19:12:23 -04:00
|
|
|
///<reference path="../typings/angularjs/angular.d.ts"/>
|
2015-08-20 16:19:34 -04:00
|
|
|
|
|
|
|
/*
|
refactor(angular_1_router): use directives for route targets
BREAKING CHANGE:
Previously, route configuration took a controller constructor function as the value of
`component` in a route definition:
```
$route.config([
{ route: '/', component: MyController }
])
```
Based on the name of the controller, we used to use a componentMapper service to
determine what template to pair with each controller, how to bind the instance to
the $scope.
To make the 1.x router more semantically alligned with Angular 2, we now route to a directive.
Thus a route configuration takes a normalized directive name:
```
$route.config([
{ route: '/', component: 'myDirective' }
])
```
BREAKING CHANGE:
In order to avoid name collisions, lifecycle hooks are now prefixed with `$`. Before:
```
MyController.prototype.onActivate = ...
```
After:
```
MyController.prototype.$onActivate = ...
```
Same for `$canActivate` (which now lives on the directive factory function),
`$canDeactivate`, `$canReuse`, and `$onDeactivate` hooks.
2015-09-18 18:53:50 -04:00
|
|
|
* decorates $compileProvider so that we have access to routing metadata
|
2015-08-20 16:19:34 -04:00
|
|
|
*/
|
2015-09-27 19:12:23 -04:00
|
|
|
function compilerProviderDecorator($compileProvider,
|
|
|
|
$$directiveIntrospectorProvider: DirectiveIntrospectorProvider) {
|
|
|
|
let directive = $compileProvider.directive;
|
|
|
|
$compileProvider.directive = function(name: string, factory: Function) {
|
refactor(angular_1_router): use directives for route targets
BREAKING CHANGE:
Previously, route configuration took a controller constructor function as the value of
`component` in a route definition:
```
$route.config([
{ route: '/', component: MyController }
])
```
Based on the name of the controller, we used to use a componentMapper service to
determine what template to pair with each controller, how to bind the instance to
the $scope.
To make the 1.x router more semantically alligned with Angular 2, we now route to a directive.
Thus a route configuration takes a normalized directive name:
```
$route.config([
{ route: '/', component: 'myDirective' }
])
```
BREAKING CHANGE:
In order to avoid name collisions, lifecycle hooks are now prefixed with `$`. Before:
```
MyController.prototype.onActivate = ...
```
After:
```
MyController.prototype.$onActivate = ...
```
Same for `$canActivate` (which now lives on the directive factory function),
`$canDeactivate`, `$canReuse`, and `$onDeactivate` hooks.
2015-09-18 18:53:50 -04:00
|
|
|
$$directiveIntrospectorProvider.register(name, factory);
|
|
|
|
return directive.apply(this, arguments);
|
2015-08-20 16:19:34 -04:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* private service that holds route mappings for each controller
|
|
|
|
*/
|
2015-09-27 19:12:23 -04:00
|
|
|
class DirectiveIntrospectorProvider {
|
|
|
|
private directiveBuffer: any[] = [];
|
|
|
|
private directiveFactoriesByName: {[name: string]: Function} = {};
|
|
|
|
private onDirectiveRegistered: (name: string, factory: Function) => any = null;
|
|
|
|
|
|
|
|
register(name: string, factory: Function) {
|
|
|
|
if (angular.isArray(factory)) {
|
|
|
|
factory = factory[factory.length - 1];
|
|
|
|
}
|
|
|
|
this.directiveFactoriesByName[name] = factory;
|
|
|
|
if (this.onDirectiveRegistered) {
|
|
|
|
this.onDirectiveRegistered(name, factory);
|
|
|
|
} else {
|
|
|
|
this.directiveBuffer.push({name: name, factory: factory});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$get() {
|
|
|
|
let fn: any = newOnControllerRegistered => {
|
|
|
|
this.onDirectiveRegistered = newOnControllerRegistered;
|
|
|
|
while (this.directiveBuffer.length > 0) {
|
|
|
|
let directive = this.directiveBuffer.pop();
|
|
|
|
this.onDirectiveRegistered(directive.name, directive.factory);
|
2015-08-20 16:19:34 -04:00
|
|
|
}
|
2015-09-27 19:12:23 -04:00
|
|
|
};
|
2015-08-20 16:19:34 -04:00
|
|
|
|
2015-09-27 19:12:23 -04:00
|
|
|
fn.getTypeByName = name => this.directiveFactoriesByName[name];
|
2015-08-20 16:19:34 -04:00
|
|
|
|
2015-09-27 19:12:23 -04:00
|
|
|
return fn;
|
|
|
|
}
|
2015-08-20 16:19:34 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @name ngOutlet
|
|
|
|
*
|
|
|
|
* @description
|
|
|
|
* An ngOutlet is where resolved content goes.
|
|
|
|
*
|
|
|
|
* ## Use
|
|
|
|
*
|
|
|
|
* ```html
|
|
|
|
* <div ng-outlet="name"></div>
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* The value for the `ngOutlet` attribute is optional.
|
|
|
|
*/
|
2015-09-27 19:12:23 -04:00
|
|
|
function ngOutletDirective($animate, $q: ng.IQService, $router) {
|
|
|
|
let rootRouter = $router;
|
2015-08-20 16:19:34 -04:00
|
|
|
|
|
|
|
return {
|
|
|
|
restrict: 'AE',
|
|
|
|
transclude: 'element',
|
|
|
|
terminal: true,
|
|
|
|
priority: 400,
|
|
|
|
require: ['?^^ngOutlet', 'ngOutlet'],
|
|
|
|
link: outletLink,
|
2015-09-27 19:12:23 -04:00
|
|
|
controller: class {},
|
2015-08-20 16:19:34 -04:00
|
|
|
controllerAs: '$$ngOutlet'
|
|
|
|
};
|
|
|
|
|
2015-09-27 19:12:23 -04:00
|
|
|
function outletLink(scope, element, attrs, ctrls, $transclude) {
|
|
|
|
class Outlet {
|
|
|
|
constructor(private controller, private router) {}
|
2015-08-20 16:19:34 -04:00
|
|
|
|
2015-09-27 19:12:23 -04:00
|
|
|
private currentController;
|
|
|
|
private currentInstruction;
|
|
|
|
private currentScope;
|
|
|
|
private currentElement;
|
|
|
|
private previousLeaveAnimation;
|
refactor(angular_1_router): use directives for route targets
BREAKING CHANGE:
Previously, route configuration took a controller constructor function as the value of
`component` in a route definition:
```
$route.config([
{ route: '/', component: MyController }
])
```
Based on the name of the controller, we used to use a componentMapper service to
determine what template to pair with each controller, how to bind the instance to
the $scope.
To make the 1.x router more semantically alligned with Angular 2, we now route to a directive.
Thus a route configuration takes a normalized directive name:
```
$route.config([
{ route: '/', component: 'myDirective' }
])
```
BREAKING CHANGE:
In order to avoid name collisions, lifecycle hooks are now prefixed with `$`. Before:
```
MyController.prototype.onActivate = ...
```
After:
```
MyController.prototype.$onActivate = ...
```
Same for `$canActivate` (which now lives on the directive factory function),
`$canDeactivate`, `$canReuse`, and `$onDeactivate` hooks.
2015-09-18 18:53:50 -04:00
|
|
|
|
2015-09-27 19:12:23 -04:00
|
|
|
private cleanupLastView() {
|
|
|
|
if (this.previousLeaveAnimation) {
|
|
|
|
$animate.cancel(this.previousLeaveAnimation);
|
|
|
|
this.previousLeaveAnimation = null;
|
|
|
|
}
|
2015-08-20 16:19:34 -04:00
|
|
|
|
2015-09-27 19:12:23 -04:00
|
|
|
if (this.currentScope) {
|
|
|
|
this.currentScope.$destroy();
|
|
|
|
this.currentScope = null;
|
|
|
|
}
|
|
|
|
if (this.currentElement) {
|
|
|
|
this.previousLeaveAnimation = $animate.leave(this.currentElement);
|
|
|
|
this.previousLeaveAnimation.then(() => this.previousLeaveAnimation = null);
|
|
|
|
this.currentElement = null;
|
|
|
|
}
|
2015-08-20 16:19:34 -04:00
|
|
|
}
|
|
|
|
|
2015-09-27 19:12:23 -04:00
|
|
|
reuse(instruction) {
|
|
|
|
let next = $q.when(true);
|
|
|
|
let previousInstruction = this.currentInstruction;
|
|
|
|
this.currentInstruction = instruction;
|
refactor(lifecycle): prefix lifecycle methods with "ng"
BREAKING CHANGE:
Previously, components that would implement lifecycle interfaces would include methods
like "onChanges" or "afterViewInit." Given that components were at risk of using such
names without realizing that Angular would call the methods at different points of
the component lifecycle. This change adds an "ng" prefix to all lifecycle hook methods,
far reducing the risk of an accidental name collision.
To fix, just rename these methods:
* onInit
* onDestroy
* doCheck
* onChanges
* afterContentInit
* afterContentChecked
* afterViewInit
* afterViewChecked
* _Router Hooks_
* onActivate
* onReuse
* onDeactivate
* canReuse
* canDeactivate
To:
* ngOnInit,
* ngOnDestroy,
* ngDoCheck,
* ngOnChanges,
* ngAfterContentInit,
* ngAfterContentChecked,
* ngAfterViewInit,
* ngAfterViewChecked
* _Router Hooks_
* routerOnActivate
* routerOnReuse
* routerOnDeactivate
* routerCanReuse
* routerCanDeactivate
The names of lifecycle interfaces and enums have not changed, though interfaces
have been updated to reflect the new method names.
Closes #5036
2015-11-16 20:04:36 -05:00
|
|
|
if (this.currentController && this.currentController.$routerOnReuse) {
|
2015-09-27 19:12:23 -04:00
|
|
|
next = $q.when(
|
refactor(lifecycle): prefix lifecycle methods with "ng"
BREAKING CHANGE:
Previously, components that would implement lifecycle interfaces would include methods
like "onChanges" or "afterViewInit." Given that components were at risk of using such
names without realizing that Angular would call the methods at different points of
the component lifecycle. This change adds an "ng" prefix to all lifecycle hook methods,
far reducing the risk of an accidental name collision.
To fix, just rename these methods:
* onInit
* onDestroy
* doCheck
* onChanges
* afterContentInit
* afterContentChecked
* afterViewInit
* afterViewChecked
* _Router Hooks_
* onActivate
* onReuse
* onDeactivate
* canReuse
* canDeactivate
To:
* ngOnInit,
* ngOnDestroy,
* ngDoCheck,
* ngOnChanges,
* ngAfterContentInit,
* ngAfterContentChecked,
* ngAfterViewInit,
* ngAfterViewChecked
* _Router Hooks_
* routerOnActivate
* routerOnReuse
* routerOnDeactivate
* routerCanReuse
* routerCanDeactivate
The names of lifecycle interfaces and enums have not changed, though interfaces
have been updated to reflect the new method names.
Closes #5036
2015-11-16 20:04:36 -05:00
|
|
|
this.currentController.$routerOnReuse(this.currentInstruction, previousInstruction));
|
2015-08-20 16:19:34 -04:00
|
|
|
}
|
2015-08-31 00:25:46 -04:00
|
|
|
|
|
|
|
return next;
|
2015-09-27 19:12:23 -04:00
|
|
|
}
|
|
|
|
|
refactor(lifecycle): prefix lifecycle methods with "ng"
BREAKING CHANGE:
Previously, components that would implement lifecycle interfaces would include methods
like "onChanges" or "afterViewInit." Given that components were at risk of using such
names without realizing that Angular would call the methods at different points of
the component lifecycle. This change adds an "ng" prefix to all lifecycle hook methods,
far reducing the risk of an accidental name collision.
To fix, just rename these methods:
* onInit
* onDestroy
* doCheck
* onChanges
* afterContentInit
* afterContentChecked
* afterViewInit
* afterViewChecked
* _Router Hooks_
* onActivate
* onReuse
* onDeactivate
* canReuse
* canDeactivate
To:
* ngOnInit,
* ngOnDestroy,
* ngDoCheck,
* ngOnChanges,
* ngAfterContentInit,
* ngAfterContentChecked,
* ngAfterViewInit,
* ngAfterViewChecked
* _Router Hooks_
* routerOnActivate
* routerOnReuse
* routerOnDeactivate
* routerCanReuse
* routerCanDeactivate
The names of lifecycle interfaces and enums have not changed, though interfaces
have been updated to reflect the new method names.
Closes #5036
2015-11-16 20:04:36 -05:00
|
|
|
routerCanReuse(nextInstruction) {
|
2015-09-27 19:12:23 -04:00
|
|
|
let result;
|
|
|
|
if (!this.currentInstruction ||
|
|
|
|
this.currentInstruction.componentType !== nextInstruction.componentType) {
|
2015-08-20 16:19:34 -04:00
|
|
|
result = false;
|
refactor(lifecycle): prefix lifecycle methods with "ng"
BREAKING CHANGE:
Previously, components that would implement lifecycle interfaces would include methods
like "onChanges" or "afterViewInit." Given that components were at risk of using such
names without realizing that Angular would call the methods at different points of
the component lifecycle. This change adds an "ng" prefix to all lifecycle hook methods,
far reducing the risk of an accidental name collision.
To fix, just rename these methods:
* onInit
* onDestroy
* doCheck
* onChanges
* afterContentInit
* afterContentChecked
* afterViewInit
* afterViewChecked
* _Router Hooks_
* onActivate
* onReuse
* onDeactivate
* canReuse
* canDeactivate
To:
* ngOnInit,
* ngOnDestroy,
* ngDoCheck,
* ngOnChanges,
* ngAfterContentInit,
* ngAfterContentChecked,
* ngAfterViewInit,
* ngAfterViewChecked
* _Router Hooks_
* routerOnActivate
* routerOnReuse
* routerOnDeactivate
* routerCanReuse
* routerCanDeactivate
The names of lifecycle interfaces and enums have not changed, though interfaces
have been updated to reflect the new method names.
Closes #5036
2015-11-16 20:04:36 -05:00
|
|
|
} else if (this.currentController && this.currentController.$routerCanReuse) {
|
|
|
|
result = this.currentController.$routerCanReuse(nextInstruction, this.currentInstruction);
|
2015-08-20 16:19:34 -04:00
|
|
|
} else {
|
2015-09-27 19:12:23 -04:00
|
|
|
result = nextInstruction === this.currentInstruction ||
|
|
|
|
angular.equals(nextInstruction.params, this.currentInstruction.params);
|
2015-08-20 16:19:34 -04:00
|
|
|
}
|
2015-08-31 00:25:46 -04:00
|
|
|
return $q.when(result);
|
2015-09-27 19:12:23 -04:00
|
|
|
}
|
|
|
|
|
refactor(lifecycle): prefix lifecycle methods with "ng"
BREAKING CHANGE:
Previously, components that would implement lifecycle interfaces would include methods
like "onChanges" or "afterViewInit." Given that components were at risk of using such
names without realizing that Angular would call the methods at different points of
the component lifecycle. This change adds an "ng" prefix to all lifecycle hook methods,
far reducing the risk of an accidental name collision.
To fix, just rename these methods:
* onInit
* onDestroy
* doCheck
* onChanges
* afterContentInit
* afterContentChecked
* afterViewInit
* afterViewChecked
* _Router Hooks_
* onActivate
* onReuse
* onDeactivate
* canReuse
* canDeactivate
To:
* ngOnInit,
* ngOnDestroy,
* ngDoCheck,
* ngOnChanges,
* ngAfterContentInit,
* ngAfterContentChecked,
* ngAfterViewInit,
* ngAfterViewChecked
* _Router Hooks_
* routerOnActivate
* routerOnReuse
* routerOnDeactivate
* routerCanReuse
* routerCanDeactivate
The names of lifecycle interfaces and enums have not changed, though interfaces
have been updated to reflect the new method names.
Closes #5036
2015-11-16 20:04:36 -05:00
|
|
|
routerCanDeactivate(instruction) {
|
|
|
|
if (this.currentController && this.currentController.$routerCanDeactivate) {
|
2015-09-27 19:12:23 -04:00
|
|
|
return $q.when(
|
refactor(lifecycle): prefix lifecycle methods with "ng"
BREAKING CHANGE:
Previously, components that would implement lifecycle interfaces would include methods
like "onChanges" or "afterViewInit." Given that components were at risk of using such
names without realizing that Angular would call the methods at different points of
the component lifecycle. This change adds an "ng" prefix to all lifecycle hook methods,
far reducing the risk of an accidental name collision.
To fix, just rename these methods:
* onInit
* onDestroy
* doCheck
* onChanges
* afterContentInit
* afterContentChecked
* afterViewInit
* afterViewChecked
* _Router Hooks_
* onActivate
* onReuse
* onDeactivate
* canReuse
* canDeactivate
To:
* ngOnInit,
* ngOnDestroy,
* ngDoCheck,
* ngOnChanges,
* ngAfterContentInit,
* ngAfterContentChecked,
* ngAfterViewInit,
* ngAfterViewChecked
* _Router Hooks_
* routerOnActivate
* routerOnReuse
* routerOnDeactivate
* routerCanReuse
* routerCanDeactivate
The names of lifecycle interfaces and enums have not changed, though interfaces
have been updated to reflect the new method names.
Closes #5036
2015-11-16 20:04:36 -05:00
|
|
|
this.currentController.$routerCanDeactivate(instruction, this.currentInstruction));
|
2015-08-20 16:19:34 -04:00
|
|
|
}
|
|
|
|
return $q.when(true);
|
2015-09-27 19:12:23 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
deactivate(instruction) {
|
refactor(lifecycle): prefix lifecycle methods with "ng"
BREAKING CHANGE:
Previously, components that would implement lifecycle interfaces would include methods
like "onChanges" or "afterViewInit." Given that components were at risk of using such
names without realizing that Angular would call the methods at different points of
the component lifecycle. This change adds an "ng" prefix to all lifecycle hook methods,
far reducing the risk of an accidental name collision.
To fix, just rename these methods:
* onInit
* onDestroy
* doCheck
* onChanges
* afterContentInit
* afterContentChecked
* afterViewInit
* afterViewChecked
* _Router Hooks_
* onActivate
* onReuse
* onDeactivate
* canReuse
* canDeactivate
To:
* ngOnInit,
* ngOnDestroy,
* ngDoCheck,
* ngOnChanges,
* ngAfterContentInit,
* ngAfterContentChecked,
* ngAfterViewInit,
* ngAfterViewChecked
* _Router Hooks_
* routerOnActivate
* routerOnReuse
* routerOnDeactivate
* routerCanReuse
* routerCanDeactivate
The names of lifecycle interfaces and enums have not changed, though interfaces
have been updated to reflect the new method names.
Closes #5036
2015-11-16 20:04:36 -05:00
|
|
|
if (this.currentController && this.currentController.$routerOnDeactivate) {
|
2015-09-27 19:12:23 -04:00
|
|
|
return $q.when(
|
refactor(lifecycle): prefix lifecycle methods with "ng"
BREAKING CHANGE:
Previously, components that would implement lifecycle interfaces would include methods
like "onChanges" or "afterViewInit." Given that components were at risk of using such
names without realizing that Angular would call the methods at different points of
the component lifecycle. This change adds an "ng" prefix to all lifecycle hook methods,
far reducing the risk of an accidental name collision.
To fix, just rename these methods:
* onInit
* onDestroy
* doCheck
* onChanges
* afterContentInit
* afterContentChecked
* afterViewInit
* afterViewChecked
* _Router Hooks_
* onActivate
* onReuse
* onDeactivate
* canReuse
* canDeactivate
To:
* ngOnInit,
* ngOnDestroy,
* ngDoCheck,
* ngOnChanges,
* ngAfterContentInit,
* ngAfterContentChecked,
* ngAfterViewInit,
* ngAfterViewChecked
* _Router Hooks_
* routerOnActivate
* routerOnReuse
* routerOnDeactivate
* routerCanReuse
* routerCanDeactivate
The names of lifecycle interfaces and enums have not changed, though interfaces
have been updated to reflect the new method names.
Closes #5036
2015-11-16 20:04:36 -05:00
|
|
|
this.currentController.$routerOnDeactivate(instruction, this.currentInstruction));
|
2015-08-31 00:25:46 -04:00
|
|
|
}
|
|
|
|
return $q.when();
|
2015-09-27 19:12:23 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
activate(instruction) {
|
|
|
|
let previousInstruction = this.currentInstruction;
|
|
|
|
this.currentInstruction = instruction;
|
refactor(angular_1_router): use directives for route targets
BREAKING CHANGE:
Previously, route configuration took a controller constructor function as the value of
`component` in a route definition:
```
$route.config([
{ route: '/', component: MyController }
])
```
Based on the name of the controller, we used to use a componentMapper service to
determine what template to pair with each controller, how to bind the instance to
the $scope.
To make the 1.x router more semantically alligned with Angular 2, we now route to a directive.
Thus a route configuration takes a normalized directive name:
```
$route.config([
{ route: '/', component: 'myDirective' }
])
```
BREAKING CHANGE:
In order to avoid name collisions, lifecycle hooks are now prefixed with `$`. Before:
```
MyController.prototype.onActivate = ...
```
After:
```
MyController.prototype.$onActivate = ...
```
Same for `$canActivate` (which now lives on the directive factory function),
`$canDeactivate`, `$canReuse`, and `$onDeactivate` hooks.
2015-09-18 18:53:50 -04:00
|
|
|
|
2015-09-27 19:12:23 -04:00
|
|
|
let componentName = this.controller.$$componentName = instruction.componentType;
|
refactor(angular_1_router): use directives for route targets
BREAKING CHANGE:
Previously, route configuration took a controller constructor function as the value of
`component` in a route definition:
```
$route.config([
{ route: '/', component: MyController }
])
```
Based on the name of the controller, we used to use a componentMapper service to
determine what template to pair with each controller, how to bind the instance to
the $scope.
To make the 1.x router more semantically alligned with Angular 2, we now route to a directive.
Thus a route configuration takes a normalized directive name:
```
$route.config([
{ route: '/', component: 'myDirective' }
])
```
BREAKING CHANGE:
In order to avoid name collisions, lifecycle hooks are now prefixed with `$`. Before:
```
MyController.prototype.onActivate = ...
```
After:
```
MyController.prototype.$onActivate = ...
```
Same for `$canActivate` (which now lives on the directive factory function),
`$canDeactivate`, `$canReuse`, and `$onDeactivate` hooks.
2015-09-18 18:53:50 -04:00
|
|
|
|
2015-09-27 19:12:23 -04:00
|
|
|
if (typeof componentName !== 'string') {
|
refactor(angular_1_router): use directives for route targets
BREAKING CHANGE:
Previously, route configuration took a controller constructor function as the value of
`component` in a route definition:
```
$route.config([
{ route: '/', component: MyController }
])
```
Based on the name of the controller, we used to use a componentMapper service to
determine what template to pair with each controller, how to bind the instance to
the $scope.
To make the 1.x router more semantically alligned with Angular 2, we now route to a directive.
Thus a route configuration takes a normalized directive name:
```
$route.config([
{ route: '/', component: 'myDirective' }
])
```
BREAKING CHANGE:
In order to avoid name collisions, lifecycle hooks are now prefixed with `$`. Before:
```
MyController.prototype.onActivate = ...
```
After:
```
MyController.prototype.$onActivate = ...
```
Same for `$canActivate` (which now lives on the directive factory function),
`$canDeactivate`, `$canReuse`, and `$onDeactivate` hooks.
2015-09-18 18:53:50 -04:00
|
|
|
throw new Error('Component is not a string for ' + instruction.urlPath);
|
|
|
|
}
|
|
|
|
|
2015-09-27 19:12:23 -04:00
|
|
|
this.controller.$$routeParams = instruction.params;
|
2016-01-31 10:35:23 -05:00
|
|
|
this.controller.$$template =
|
2016-02-07 15:40:00 -05:00
|
|
|
'<' + dashCase(componentName) + ' router="$$router"></' + dashCase(componentName) + '>';
|
2015-09-27 19:12:23 -04:00
|
|
|
this.controller.$$router = this.router.childRouter(instruction.componentType);
|
refactor(angular_1_router): use directives for route targets
BREAKING CHANGE:
Previously, route configuration took a controller constructor function as the value of
`component` in a route definition:
```
$route.config([
{ route: '/', component: MyController }
])
```
Based on the name of the controller, we used to use a componentMapper service to
determine what template to pair with each controller, how to bind the instance to
the $scope.
To make the 1.x router more semantically alligned with Angular 2, we now route to a directive.
Thus a route configuration takes a normalized directive name:
```
$route.config([
{ route: '/', component: 'myDirective' }
])
```
BREAKING CHANGE:
In order to avoid name collisions, lifecycle hooks are now prefixed with `$`. Before:
```
MyController.prototype.onActivate = ...
```
After:
```
MyController.prototype.$onActivate = ...
```
Same for `$canActivate` (which now lives on the directive factory function),
`$canDeactivate`, `$canReuse`, and `$onDeactivate` hooks.
2015-09-18 18:53:50 -04:00
|
|
|
|
2015-09-27 19:12:23 -04:00
|
|
|
let newScope = scope.$new();
|
2016-02-07 15:40:00 -05:00
|
|
|
newScope.$$router = this.controller.$$router;
|
refactor(angular_1_router): use directives for route targets
BREAKING CHANGE:
Previously, route configuration took a controller constructor function as the value of
`component` in a route definition:
```
$route.config([
{ route: '/', component: MyController }
])
```
Based on the name of the controller, we used to use a componentMapper service to
determine what template to pair with each controller, how to bind the instance to
the $scope.
To make the 1.x router more semantically alligned with Angular 2, we now route to a directive.
Thus a route configuration takes a normalized directive name:
```
$route.config([
{ route: '/', component: 'myDirective' }
])
```
BREAKING CHANGE:
In order to avoid name collisions, lifecycle hooks are now prefixed with `$`. Before:
```
MyController.prototype.onActivate = ...
```
After:
```
MyController.prototype.$onActivate = ...
```
Same for `$canActivate` (which now lives on the directive factory function),
`$canDeactivate`, `$canReuse`, and `$onDeactivate` hooks.
2015-09-18 18:53:50 -04:00
|
|
|
|
2015-09-27 19:12:23 -04:00
|
|
|
let clone = $transclude(newScope, clone => {
|
|
|
|
$animate.enter(clone, null, this.currentElement || element);
|
|
|
|
this.cleanupLastView();
|
2015-08-20 16:19:34 -04:00
|
|
|
});
|
refactor(angular_1_router): use directives for route targets
BREAKING CHANGE:
Previously, route configuration took a controller constructor function as the value of
`component` in a route definition:
```
$route.config([
{ route: '/', component: MyController }
])
```
Based on the name of the controller, we used to use a componentMapper service to
determine what template to pair with each controller, how to bind the instance to
the $scope.
To make the 1.x router more semantically alligned with Angular 2, we now route to a directive.
Thus a route configuration takes a normalized directive name:
```
$route.config([
{ route: '/', component: 'myDirective' }
])
```
BREAKING CHANGE:
In order to avoid name collisions, lifecycle hooks are now prefixed with `$`. Before:
```
MyController.prototype.onActivate = ...
```
After:
```
MyController.prototype.$onActivate = ...
```
Same for `$canActivate` (which now lives on the directive factory function),
`$canDeactivate`, `$canReuse`, and `$onDeactivate` hooks.
2015-09-18 18:53:50 -04:00
|
|
|
|
2015-09-27 19:12:23 -04:00
|
|
|
this.currentElement = clone;
|
|
|
|
this.currentScope = newScope;
|
refactor(angular_1_router): use directives for route targets
BREAKING CHANGE:
Previously, route configuration took a controller constructor function as the value of
`component` in a route definition:
```
$route.config([
{ route: '/', component: MyController }
])
```
Based on the name of the controller, we used to use a componentMapper service to
determine what template to pair with each controller, how to bind the instance to
the $scope.
To make the 1.x router more semantically alligned with Angular 2, we now route to a directive.
Thus a route configuration takes a normalized directive name:
```
$route.config([
{ route: '/', component: 'myDirective' }
])
```
BREAKING CHANGE:
In order to avoid name collisions, lifecycle hooks are now prefixed with `$`. Before:
```
MyController.prototype.onActivate = ...
```
After:
```
MyController.prototype.$onActivate = ...
```
Same for `$canActivate` (which now lives on the directive factory function),
`$canDeactivate`, `$canReuse`, and `$onDeactivate` hooks.
2015-09-18 18:53:50 -04:00
|
|
|
|
|
|
|
// TODO: prefer the other directive retrieving the controller
|
|
|
|
// by debug mode
|
2015-09-27 19:12:23 -04:00
|
|
|
this.currentController = this.currentElement.children().eq(0).controller(componentName);
|
refactor(angular_1_router): use directives for route targets
BREAKING CHANGE:
Previously, route configuration took a controller constructor function as the value of
`component` in a route definition:
```
$route.config([
{ route: '/', component: MyController }
])
```
Based on the name of the controller, we used to use a componentMapper service to
determine what template to pair with each controller, how to bind the instance to
the $scope.
To make the 1.x router more semantically alligned with Angular 2, we now route to a directive.
Thus a route configuration takes a normalized directive name:
```
$route.config([
{ route: '/', component: 'myDirective' }
])
```
BREAKING CHANGE:
In order to avoid name collisions, lifecycle hooks are now prefixed with `$`. Before:
```
MyController.prototype.onActivate = ...
```
After:
```
MyController.prototype.$onActivate = ...
```
Same for `$canActivate` (which now lives on the directive factory function),
`$canDeactivate`, `$canReuse`, and `$onDeactivate` hooks.
2015-09-18 18:53:50 -04:00
|
|
|
|
refactor(lifecycle): prefix lifecycle methods with "ng"
BREAKING CHANGE:
Previously, components that would implement lifecycle interfaces would include methods
like "onChanges" or "afterViewInit." Given that components were at risk of using such
names without realizing that Angular would call the methods at different points of
the component lifecycle. This change adds an "ng" prefix to all lifecycle hook methods,
far reducing the risk of an accidental name collision.
To fix, just rename these methods:
* onInit
* onDestroy
* doCheck
* onChanges
* afterContentInit
* afterContentChecked
* afterViewInit
* afterViewChecked
* _Router Hooks_
* onActivate
* onReuse
* onDeactivate
* canReuse
* canDeactivate
To:
* ngOnInit,
* ngOnDestroy,
* ngDoCheck,
* ngOnChanges,
* ngAfterContentInit,
* ngAfterContentChecked,
* ngAfterViewInit,
* ngAfterViewChecked
* _Router Hooks_
* routerOnActivate
* routerOnReuse
* routerOnDeactivate
* routerCanReuse
* routerCanDeactivate
The names of lifecycle interfaces and enums have not changed, though interfaces
have been updated to reflect the new method names.
Closes #5036
2015-11-16 20:04:36 -05:00
|
|
|
if (this.currentController && this.currentController.$routerOnActivate) {
|
|
|
|
return this.currentController.$routerOnActivate(instruction, previousInstruction);
|
refactor(angular_1_router): use directives for route targets
BREAKING CHANGE:
Previously, route configuration took a controller constructor function as the value of
`component` in a route definition:
```
$route.config([
{ route: '/', component: MyController }
])
```
Based on the name of the controller, we used to use a componentMapper service to
determine what template to pair with each controller, how to bind the instance to
the $scope.
To make the 1.x router more semantically alligned with Angular 2, we now route to a directive.
Thus a route configuration takes a normalized directive name:
```
$route.config([
{ route: '/', component: 'myDirective' }
])
```
BREAKING CHANGE:
In order to avoid name collisions, lifecycle hooks are now prefixed with `$`. Before:
```
MyController.prototype.onActivate = ...
```
After:
```
MyController.prototype.$onActivate = ...
```
Same for `$canActivate` (which now lives on the directive factory function),
`$canDeactivate`, `$canReuse`, and `$onDeactivate` hooks.
2015-09-18 18:53:50 -04:00
|
|
|
}
|
|
|
|
return $q.when();
|
2015-08-20 16:19:34 -04:00
|
|
|
}
|
2015-09-27 19:12:23 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
let parentCtrl = ctrls[0], myCtrl = ctrls[1],
|
|
|
|
router = (parentCtrl && parentCtrl.$$router) || rootRouter;
|
|
|
|
|
|
|
|
myCtrl.$$currentComponent = null;
|
|
|
|
|
|
|
|
router.registerPrimaryOutlet(new Outlet(myCtrl, router));
|
2015-08-20 16:19:34 -04:00
|
|
|
}
|
|
|
|
}
|
refactor(angular_1_router): use directives for route targets
BREAKING CHANGE:
Previously, route configuration took a controller constructor function as the value of
`component` in a route definition:
```
$route.config([
{ route: '/', component: MyController }
])
```
Based on the name of the controller, we used to use a componentMapper service to
determine what template to pair with each controller, how to bind the instance to
the $scope.
To make the 1.x router more semantically alligned with Angular 2, we now route to a directive.
Thus a route configuration takes a normalized directive name:
```
$route.config([
{ route: '/', component: 'myDirective' }
])
```
BREAKING CHANGE:
In order to avoid name collisions, lifecycle hooks are now prefixed with `$`. Before:
```
MyController.prototype.onActivate = ...
```
After:
```
MyController.prototype.$onActivate = ...
```
Same for `$canActivate` (which now lives on the directive factory function),
`$canDeactivate`, `$canReuse`, and `$onDeactivate` hooks.
2015-09-18 18:53:50 -04:00
|
|
|
/**
|
|
|
|
* This directive is responsible for compiling the contents of ng-outlet
|
|
|
|
*/
|
2015-08-20 16:19:34 -04:00
|
|
|
function ngOutletFillContentDirective($compile) {
|
|
|
|
return {
|
|
|
|
restrict: 'EA',
|
|
|
|
priority: -400,
|
|
|
|
require: 'ngOutlet',
|
2015-09-27 19:12:23 -04:00
|
|
|
link: (scope, element, attrs, ctrl) => {
|
|
|
|
let template = ctrl.$$template;
|
|
|
|
element.html(template);
|
|
|
|
let link = $compile(element.contents());
|
2015-08-20 16:19:34 -04:00
|
|
|
link(scope);
|
refactor(angular_1_router): use directives for route targets
BREAKING CHANGE:
Previously, route configuration took a controller constructor function as the value of
`component` in a route definition:
```
$route.config([
{ route: '/', component: MyController }
])
```
Based on the name of the controller, we used to use a componentMapper service to
determine what template to pair with each controller, how to bind the instance to
the $scope.
To make the 1.x router more semantically alligned with Angular 2, we now route to a directive.
Thus a route configuration takes a normalized directive name:
```
$route.config([
{ route: '/', component: 'myDirective' }
])
```
BREAKING CHANGE:
In order to avoid name collisions, lifecycle hooks are now prefixed with `$`. Before:
```
MyController.prototype.onActivate = ...
```
After:
```
MyController.prototype.$onActivate = ...
```
Same for `$canActivate` (which now lives on the directive factory function),
`$canDeactivate`, `$canReuse`, and `$onDeactivate` hooks.
2015-09-18 18:53:50 -04:00
|
|
|
|
|
|
|
// TODO: move to primary directive
|
2015-09-27 19:12:23 -04:00
|
|
|
let componentInstance = scope[ctrl.$$componentName];
|
refactor(angular_1_router): use directives for route targets
BREAKING CHANGE:
Previously, route configuration took a controller constructor function as the value of
`component` in a route definition:
```
$route.config([
{ route: '/', component: MyController }
])
```
Based on the name of the controller, we used to use a componentMapper service to
determine what template to pair with each controller, how to bind the instance to
the $scope.
To make the 1.x router more semantically alligned with Angular 2, we now route to a directive.
Thus a route configuration takes a normalized directive name:
```
$route.config([
{ route: '/', component: 'myDirective' }
])
```
BREAKING CHANGE:
In order to avoid name collisions, lifecycle hooks are now prefixed with `$`. Before:
```
MyController.prototype.onActivate = ...
```
After:
```
MyController.prototype.$onActivate = ...
```
Same for `$canActivate` (which now lives on the directive factory function),
`$canDeactivate`, `$canReuse`, and `$onDeactivate` hooks.
2015-09-18 18:53:50 -04:00
|
|
|
if (componentInstance) {
|
|
|
|
ctrl.$$currentComponent = componentInstance;
|
|
|
|
|
|
|
|
componentInstance.$router = ctrl.$$router;
|
|
|
|
componentInstance.$routeParams = ctrl.$$routeParams;
|
|
|
|
}
|
2015-08-20 16:19:34 -04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @name ngLink
|
|
|
|
* @description
|
|
|
|
* Lets you link to different parts of the app, and automatically generates hrefs.
|
|
|
|
*
|
|
|
|
* ## Use
|
|
|
|
* The directive uses a simple syntax: `ng-link="componentName({ param: paramValue })"`
|
|
|
|
*
|
2015-10-19 10:37:32 -04:00
|
|
|
* ### Example
|
2015-08-20 16:19:34 -04:00
|
|
|
*
|
|
|
|
* ```js
|
2015-09-27 19:12:23 -04:00
|
|
|
* angular.module('myApp', ['ngComponentRouter'])
|
2015-08-20 16:19:34 -04:00
|
|
|
* .controller('AppController', ['$router', function($router) {
|
2015-09-27 19:12:23 -04:00
|
|
|
* $router.config({ path: '/user/:id', component: 'user' });
|
2015-08-20 16:19:34 -04:00
|
|
|
* this.user = { name: 'Brian', id: 123 };
|
|
|
|
* });
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* ```html
|
|
|
|
* <div ng-controller="AppController as app">
|
|
|
|
* <a ng-link="user({id: app.user.id})">{{app.user.name}}</a>
|
|
|
|
* </div>
|
|
|
|
* ```
|
|
|
|
*/
|
refactor(angular_1_router): use directives for route targets
BREAKING CHANGE:
Previously, route configuration took a controller constructor function as the value of
`component` in a route definition:
```
$route.config([
{ route: '/', component: MyController }
])
```
Based on the name of the controller, we used to use a componentMapper service to
determine what template to pair with each controller, how to bind the instance to
the $scope.
To make the 1.x router more semantically alligned with Angular 2, we now route to a directive.
Thus a route configuration takes a normalized directive name:
```
$route.config([
{ route: '/', component: 'myDirective' }
])
```
BREAKING CHANGE:
In order to avoid name collisions, lifecycle hooks are now prefixed with `$`. Before:
```
MyController.prototype.onActivate = ...
```
After:
```
MyController.prototype.$onActivate = ...
```
Same for `$canActivate` (which now lives on the directive factory function),
`$canDeactivate`, `$canReuse`, and `$onDeactivate` hooks.
2015-09-18 18:53:50 -04:00
|
|
|
function ngLinkDirective($router, $parse) {
|
2015-09-27 19:12:23 -04:00
|
|
|
let rootRouter = $router;
|
2015-08-20 16:19:34 -04:00
|
|
|
|
2015-09-27 19:12:23 -04:00
|
|
|
return {require: '?^^ngOutlet', restrict: 'A', link: ngLinkDirectiveLinkFn};
|
2015-08-20 16:19:34 -04:00
|
|
|
|
2015-09-27 19:12:23 -04:00
|
|
|
function ngLinkDirectiveLinkFn(scope, element, attrs, ctrl) {
|
|
|
|
let router = (ctrl && ctrl.$$router) || rootRouter;
|
2015-08-20 16:19:34 -04:00
|
|
|
if (!router) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-09-27 19:12:23 -04:00
|
|
|
let instruction = null;
|
|
|
|
let link = attrs.ngLink || '';
|
2015-08-20 16:19:34 -04:00
|
|
|
|
|
|
|
function getLink(params) {
|
refactor(angular_1_router): use directives for route targets
BREAKING CHANGE:
Previously, route configuration took a controller constructor function as the value of
`component` in a route definition:
```
$route.config([
{ route: '/', component: MyController }
])
```
Based on the name of the controller, we used to use a componentMapper service to
determine what template to pair with each controller, how to bind the instance to
the $scope.
To make the 1.x router more semantically alligned with Angular 2, we now route to a directive.
Thus a route configuration takes a normalized directive name:
```
$route.config([
{ route: '/', component: 'myDirective' }
])
```
BREAKING CHANGE:
In order to avoid name collisions, lifecycle hooks are now prefixed with `$`. Before:
```
MyController.prototype.onActivate = ...
```
After:
```
MyController.prototype.$onActivate = ...
```
Same for `$canActivate` (which now lives on the directive factory function),
`$canDeactivate`, `$canReuse`, and `$onDeactivate` hooks.
2015-09-18 18:53:50 -04:00
|
|
|
instruction = router.generate(params);
|
|
|
|
return './' + angular.stringifyInstruction(instruction);
|
2015-08-20 16:19:34 -04:00
|
|
|
}
|
|
|
|
|
2015-09-27 19:12:23 -04:00
|
|
|
let routeParamsGetter = $parse(link);
|
2015-08-20 16:19:34 -04:00
|
|
|
// we can avoid adding a watcher if it's a literal
|
|
|
|
if (routeParamsGetter.constant) {
|
2015-09-27 19:12:23 -04:00
|
|
|
let params = routeParamsGetter();
|
|
|
|
element.attr('href', getLink(params));
|
2015-08-20 16:19:34 -04:00
|
|
|
} else {
|
2015-09-27 19:12:23 -04:00
|
|
|
scope.$watch(() => routeParamsGetter(scope), params => element.attr('href', getLink(params)),
|
|
|
|
true);
|
2015-08-20 16:19:34 -04:00
|
|
|
}
|
|
|
|
|
2015-09-27 19:12:23 -04:00
|
|
|
element.on('click', event => {
|
refactor(angular_1_router): use directives for route targets
BREAKING CHANGE:
Previously, route configuration took a controller constructor function as the value of
`component` in a route definition:
```
$route.config([
{ route: '/', component: MyController }
])
```
Based on the name of the controller, we used to use a componentMapper service to
determine what template to pair with each controller, how to bind the instance to
the $scope.
To make the 1.x router more semantically alligned with Angular 2, we now route to a directive.
Thus a route configuration takes a normalized directive name:
```
$route.config([
{ route: '/', component: 'myDirective' }
])
```
BREAKING CHANGE:
In order to avoid name collisions, lifecycle hooks are now prefixed with `$`. Before:
```
MyController.prototype.onActivate = ...
```
After:
```
MyController.prototype.$onActivate = ...
```
Same for `$canActivate` (which now lives on the directive factory function),
`$canDeactivate`, `$canReuse`, and `$onDeactivate` hooks.
2015-09-18 18:53:50 -04:00
|
|
|
if (event.which !== 1 || !instruction) {
|
2015-08-20 16:19:34 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
refactor(angular_1_router): use directives for route targets
BREAKING CHANGE:
Previously, route configuration took a controller constructor function as the value of
`component` in a route definition:
```
$route.config([
{ route: '/', component: MyController }
])
```
Based on the name of the controller, we used to use a componentMapper service to
determine what template to pair with each controller, how to bind the instance to
the $scope.
To make the 1.x router more semantically alligned with Angular 2, we now route to a directive.
Thus a route configuration takes a normalized directive name:
```
$route.config([
{ route: '/', component: 'myDirective' }
])
```
BREAKING CHANGE:
In order to avoid name collisions, lifecycle hooks are now prefixed with `$`. Before:
```
MyController.prototype.onActivate = ...
```
After:
```
MyController.prototype.$onActivate = ...
```
Same for `$canActivate` (which now lives on the directive factory function),
`$canDeactivate`, `$canReuse`, and `$onDeactivate` hooks.
2015-09-18 18:53:50 -04:00
|
|
|
$router.navigateByInstruction(instruction);
|
|
|
|
event.preventDefault();
|
|
|
|
});
|
|
|
|
}
|
2015-08-20 16:19:34 -04:00
|
|
|
}
|
|
|
|
|
2015-09-27 19:12:23 -04:00
|
|
|
function dashCase(str: string): string {
|
|
|
|
return str.replace(/[A-Z]/g, match => '-' + match.toLowerCase());
|
2015-08-20 16:19:34 -04:00
|
|
|
}
|
2015-09-27 19:12:23 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* A module for adding new a routing system Angular 1.
|
|
|
|
*/
|
|
|
|
angular.module('ngComponentRouter', [])
|
2015-11-04 06:48:06 -05:00
|
|
|
.directive('ngOutlet', ['$animate', '$q', '$router', ngOutletDirective])
|
|
|
|
.directive('ngOutlet', ['$compile', ngOutletFillContentDirective])
|
|
|
|
.directive('ngLink', ['$router', '$parse', ngLinkDirective]);
|
2015-09-27 19:12:23 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* A module for inspecting controller constructors
|
|
|
|
*/
|
|
|
|
angular.module('ng')
|
|
|
|
.provider('$$directiveIntrospector', DirectiveIntrospectorProvider)
|
2015-11-04 06:48:06 -05:00
|
|
|
.config(['$compileProvider', '$$directiveIntrospectorProvider', compilerProviderDecorator]);
|