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.
This commit is contained in:
Brian Ford
2015-09-18 15:53:50 -07:00
parent 6e0ca7f39a
commit 5205a9e65f
12 changed files with 547 additions and 724 deletions

View File

@ -22,12 +22,12 @@ var PRELUDE = '(function(){\n';
var POSTLUDE = '\n}());\n';
var FACADES = fs.readFileSync(__dirname + '/lib/facades.es5', 'utf8');
var DIRECTIVES = fs.readFileSync(__dirname + '/src/ng_outlet.js', 'utf8');
var moduleTemplate = fs.readFileSync(__dirname + '/src/module_template.js', 'utf8');
function main() {
var ES6_SHIM = fs.readFileSync(__dirname + '/../../node_modules/es6-shim/es6-shim.js', 'utf8');
var dir = __dirname + '/../angular2/src/router/';
var out = '';
var sharedCode = '';
files.forEach(function (file) {
var moduleName = 'router/' + file.replace(/\.ts$/, '');
@ -35,57 +35,9 @@ function main() {
sharedCode += transform(moduleName, fs.readFileSync(dir + file, 'utf8'));
});
out += "angular.module('ngComponentRouter')";
out += angularFactory('$router', ['$q', '$location', '$$controllerIntrospector',
'$browser', '$rootScope', '$injector'], [
FACADES,
"var exports = {Injectable: function () {}};",
"var require = function () {return exports;};",
sharedCode,
"var RouteConfig = exports.RouteConfig;",
"angular.annotations = {RouteConfig: RouteConfig, CanActivate: exports.CanActivate};",
"angular.stringifyInstruction = exports.stringifyInstruction;",
"var RouteRegistry = exports.RouteRegistry;",
"var RootRouter = exports.RootRouter;",
//TODO: move this code into a templated JS file
"var registry = new RouteRegistry();",
"var location = new Location();",
var out = moduleTemplate.replace('//{{FACADES}}', FACADES).replace('//{{SHARED_CODE}}', sharedCode);
"$$controllerIntrospector(function (name, constructor) {",
"if (constructor.$canActivate) {",
"constructor.annotations = constructor.annotations || [];",
"constructor.annotations.push(new angular.annotations.CanActivate(function (instruction) {",
"return $injector.invoke(constructor.$canActivate, constructor, {",
"$routeParams: instruction.component ? instruction.component.params : instruction.params",
"});",
"}));",
"}",
"if (constructor.$routeConfig) {",
"constructor.annotations = constructor.annotations || [];",
"constructor.annotations.push(new angular.annotations.RouteConfig(constructor.$routeConfig));",
"}",
"if (constructor.annotations) {",
"constructor.annotations.forEach(function(annotation) {",
"if (annotation instanceof RouteConfig) {",
"annotation.configs.forEach(function (config) {",
"registry.config(constructor, config);",
"});",
"}",
"});",
"}",
"});",
"var router = new RootRouter(registry, location, new Object());",
"$rootScope.$watch(function () { return $location.path(); }, function (path) {",
"if (router.lastNavigationAttempt !== path) {",
"router.navigateByUrl(path);",
"}",
"});",
"return router;"
].join('\n'));
return PRELUDE + ES6_SHIM + DIRECTIVES + out + POSTLUDE;
return PRELUDE + DIRECTIVES + out + POSTLUDE;
}