Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

feat(1.x): support routing to a directive #228

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
6 changes: 5 additions & 1 deletion dist/grammar.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions dist/pipeline.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

133 changes: 123 additions & 10 deletions dist/router.es5.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ angular.module('ngNewRouter', [])
.factory('$setupRoutersStep', setupRoutersStepFactory)
.factory('$initLocalsStep', initLocalsStepFactory)
.factory('$initControllersStep', initControllersStepFactory)
.factory('$bindRouteParamsForDirectiveStep', bindRouteParamsForDirectiveStepFactory)
.factory('$runCanDeactivateHookStep', runCanDeactivateHookStepFactory)
.factory('$runCanActivateHookStep', runCanActivateHookStepFactory)
.factory('$loadTemplatesStep', loadTemplatesStepFactory)
Expand All @@ -29,7 +30,9 @@ angular.module('ngNewRouter', [])
*/
angular.module('ng')
.provider('$controllerIntrospector', $controllerIntrospectorProvider)
.config(controllerProviderDecorator);
.provider('$compileIntrospector', $compileIntrospectorProvider)
.config(controllerProviderDecorator)
.config(compileProviderDecorator);

/*
* decorates with routing info
Expand All @@ -43,6 +46,15 @@ function controllerProviderDecorator($controllerProvider, $controllerIntrospecto
}
controllerProviderDecorator.$inject = ["$controllerProvider", "$controllerIntrospectorProvider"];

function compileProviderDecorator($compileProvider, $compileIntrospectorProvider) {
var directive = $compileProvider.directive;
$compileProvider.directive = function (name, directiveFactory) {
$compileIntrospectorProvider.directive(name, directiveFactory);
return directive.apply(this, arguments);
};
}
compileProviderDecorator.$inject = ["$compileProvider", "$compileIntrospectorProvider"];

/*
* private service that holds route mappings for each controller
*/
Expand Down Expand Up @@ -77,12 +89,50 @@ function $controllerIntrospectorProvider() {
}
}

function routerFactory($$rootRouter, $rootScope, $location, $$grammar, $controllerIntrospector) {

/*
* private service that holds route mappings for each controller
*/
function $compileIntrospectorProvider() {
var directiveFactories = [];
var onDirectiveDefined = null;
return {
directive: function (name, directiveFactory) {
if (angular.isArray(directiveFactory)) {
directiveFactory = directiveFactory[directiveFactory.length - 1];
}
if (directiveFactory.$routeConfig) {
if (onDirectiveDefined) {
onDirectiveDefined(name, directiveFactory.$routeConfig);
} else {
directiveFactories.push({name: name, config: directiveFactory.$routeConfig});
}
}
},
$get: ['$componentLoader', '$injector', function ($componentLoader, $injector) {
return function (newOnDirectiveDefined) {
onDirectiveDefined = function (name, config) {
return newOnDirectiveDefined(name, config);
};
while(directiveFactories.length > 0) {
var rule = directiveFactories.pop();
onDirectiveDefined(rule.name, rule.config);
}
}
}]
}
}

function routerFactory($$rootRouter, $rootScope, $location, $$grammar, $controllerIntrospector, $compileIntrospector) {

$controllerIntrospector(function (name, config) {
$$grammar.config(name, config);
});

$compileIntrospector(function (name, config) {
$$grammar.config(name, config);
});

$rootScope.$watch(function () {
return $location.path();
}, function (newUrl) {
Expand All @@ -100,7 +150,7 @@ function routerFactory($$rootRouter, $rootScope, $location, $$grammar, $controll

return $$rootRouter;
}
routerFactory.$inject = ["$$rootRouter", "$rootScope", "$location", "$$grammar", "$controllerIntrospector"];
routerFactory.$inject = ["$$rootRouter", "$rootScope", "$location", "$$grammar", "$controllerIntrospector", "$compileIntrospector"];

/**
* @name ngViewport
Expand Down Expand Up @@ -189,7 +239,11 @@ function ngViewportDirective($animate, $injector, $q, $router) {
});

var newController = instruction.controller;
newScope[componentName] = newController;
if (instruction.directive && instruction.directive.controllerAs) {
newScope[instruction.directive.controllerAs] = newController;
} else {
newScope[componentName] = newController;
}

var result;
if (currentController && currentController.deactivate) {
Expand Down Expand Up @@ -372,23 +426,56 @@ function initLocalsStepFactory() {
/*
* $initControllersStep
*/
function initControllersStepFactory($controller, $componentLoader) {
function initControllersStepFactory($controller, $componentLoader, $injector) {
return function initControllers(instruction) {
return instruction.router.traverseInstruction(instruction, function(instruction) {
var controllerName = $componentLoader.controllerName(instruction.component);
var directiveName = $componentLoader.directiveName(instruction.component);
var locals = instruction.locals;
var ctrl;
try {
ctrl = $controller(controllerName, locals);
} catch(e) {
console.warn && console.warn('Could not instantiate controller', controllerName);
ctrl = $controller(angular.noop, locals);
try {
var directives = $injector.get(directiveName);
// can't handle two names on the same directive yet
instruction.directive = directives[0];
ctrl = $controller(instruction.directive.controller, locals);
} catch(e) {
console.warn && console.warn('Could not instantiate controller', controllerName);
ctrl = $controller(angular.noop, locals);
}
}
return instruction.controller = ctrl;
});
}
}
initControllersStepFactory.$inject = ["$controller", "$componentLoader"];
initControllersStepFactory.$inject = ["$controller", "$componentLoader", "$injector"];

function bindRouteParamsForDirectiveStepFactory() {
return function bindRouteParamsForDirective(instruction) {
return instruction.router.traverseInstruction(instruction, function(instruction) {
if (instruction.directive && instruction.directive.bindToController) {
var bindings;
if (typeof instruction.directive.bindToController == 'object') {
// ng 1.4 object syntax
bindings = instruction.directive.$$bindings.bindToController;
} else if (instruction.directive.bindToController == true) {
// ng 1.3 syntax
bindings = instruction.directive.$$isolateBindings;
}
if (bindings) {
Object.keys(bindings).forEach(function(key) {
if (instruction.params[bindings[key].attrName]) {
instruction.controller[key] = instruction.params[bindings[key].attrName];
}
});
}
}
return true;
});
};
}

function runCanDeactivateHookStepFactory() {
return function runCanDeactivateHook(instruction) {
Expand Down Expand Up @@ -416,7 +503,16 @@ runCanActivateHookStepFactory.$inject = ["$injector"];
function loadTemplatesStepFactory($componentLoader, $templateRequest) {
return function loadTemplates(instruction) {
return instruction.router.traverseInstruction(instruction, function(instruction) {
var componentTemplateUrl = $componentLoader.template(instruction.component);
var componentTemplateUrl;
if (instruction.directive) {
if (instruction.directive.template) {
return instruction.template = instruction.directive.template
} else {
componentTemplateUrl = instruction.directive.templateUrl;
}
} else {
componentTemplateUrl = $componentLoader.template(instruction.component);
}
return $templateRequest(componentTemplateUrl).then(function (templateHtml) {
return instruction.template = templateHtml;
});
Expand All @@ -438,6 +534,7 @@ function pipelineProvider() {
'$setupRoutersStep',
'$initLocalsStep',
'$initControllersStep',
'$bindRouteParamsForDirectiveStep',
'$runCanDeactivateHookStep',
'$runCanActivateHookStep',
'$loadTemplatesStep',
Expand Down Expand Up @@ -493,6 +590,7 @@ function pipelineProvider() {
function $componentLoaderProvider() {

var DEFAULT_SUFFIX = 'Controller';
var DEFAULT_DIRECTIVE_SUFFIX = 'Directive';

var componentToCtrl = function componentToCtrlDefault(name) {
return name[0].toUpperCase() + name.substr(1) + DEFAULT_SUFFIX;
Expand All @@ -507,12 +605,22 @@ function $componentLoaderProvider() {
return name[0].toLowerCase() + name.substr(1, name.length - DEFAULT_SUFFIX.length - 1);
};

var componentToDirective = function componentToDirectiveDefault(name) {
return name + DEFAULT_DIRECTIVE_SUFFIX;
};

var directiveToComponent = function directiveToComponent(name) {
return name.substr(0, name.length - DEFAULT_DIRECTIVE_SUFFIX.length);
};

return {
$get: function () {
return {
controllerName: componentToCtrl,
template: componentToTemplate,
component: ctrlToComponent
component: ctrlToComponent,
directiveName: componentToDirective,
directiveToComponent: directiveToComponent
};
},

Expand Down Expand Up @@ -541,6 +649,11 @@ function $componentLoaderProvider() {
setTemplateMapping: function(newFn) {
componentToTemplate = newFn;
return this;
},

setDirectiveMapping: function(newFn) {
componentToDirective = newFn;
return this;
}
};
}
Expand Down
2 changes: 1 addition & 1 deletion dist/router.es5.min.js

Large diffs are not rendered by default.

14 changes: 11 additions & 3 deletions dist/router.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading