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;
|
|
|
|
if (this.currentController && this.currentController.$onReuse) {
|
|
|
|
next = $q.when(
|
|
|
|
this.currentController.$onReuse(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
|
|
|
}
|
|
|
|
|
|
|
|
canReuse(nextInstruction) {
|
|
|
|
let result;
|
|
|
|
if (!this.currentInstruction ||
|
|
|
|
this.currentInstruction.componentType !== nextInstruction.componentType) {
|
2015-08-20 16:19:34 -04:00
|
|
|
result = false;
|
2015-09-27 19:12:23 -04:00
|
|
|
} else if (this.currentController && this.currentController.$canReuse) {
|
|
|
|
result = this.currentController.$canReuse(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
|
|
|
}
|
|
|
|
|
|
|
|
canDeactivate(instruction) {
|
|
|
|
if (this.currentController && this.currentController.$canDeactivate) {
|
|
|
|
return $q.when(
|
|
|
|
this.currentController.$canDeactivate(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) {
|
|
|
|
if (this.currentController && this.currentController.$onDeactivate) {
|
|
|
|
return $q.when(
|
|
|
|
this.currentController.$onDeactivate(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;
|
|
|
|
this.controller.$$template = '<div ' + dashCase(componentName) + '></div>';
|
|
|
|
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();
|
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
|
|
|
|
2015-09-27 19:12:23 -04:00
|
|
|
if (this.currentController && this.currentController.$onActivate) {
|
|
|
|
return this.currentController.$onActivate(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', [])
|
|
|
|
.directive('ngOutlet', ngOutletDirective)
|
|
|
|
.directive('ngOutlet', ngOutletFillContentDirective)
|
|
|
|
.directive('ngLink', ngLinkDirective);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* A module for inspecting controller constructors
|
|
|
|
*/
|
|
|
|
angular.module('ng')
|
|
|
|
.provider('$$directiveIntrospector', DirectiveIntrospectorProvider)
|
|
|
|
.config(compilerProviderDecorator);
|