fix(angular1_router): support templateUrl components
This commit is contained in:
parent
e7470d557d
commit
d4a4d81173
|
@ -145,7 +145,7 @@ function ngOutletDirective($animate, $q: ng.IQService, $router) {
|
|||
}
|
||||
|
||||
activate(instruction) {
|
||||
let previousInstruction = this.currentInstruction;
|
||||
this.previousInstruction = this.currentInstruction;
|
||||
this.currentInstruction = instruction;
|
||||
|
||||
let componentName = this.controller.$$componentName = instruction.componentType;
|
||||
|
@ -154,13 +154,14 @@ function ngOutletDirective($animate, $q: ng.IQService, $router) {
|
|||
throw new Error('Component is not a string for ' + instruction.urlPath);
|
||||
}
|
||||
|
||||
this.controller.$$routeParams = instruction.params;
|
||||
this.controller.$$template =
|
||||
'<' + dashCase(componentName) + ' router="$$router"></' + dashCase(componentName) + '>';
|
||||
this.controller.$$router = this.router.childRouter(instruction.componentType);
|
||||
this.controller.$$outlet = this;
|
||||
|
||||
let newScope = scope.$new();
|
||||
newScope.$$router = this.controller.$$router;
|
||||
this.deferredActivation = $q.defer();
|
||||
|
||||
let clone = $transclude(newScope, clone => {
|
||||
$animate.enter(clone, null, this.currentElement || element);
|
||||
|
@ -169,15 +170,7 @@ function ngOutletDirective($animate, $q: ng.IQService, $router) {
|
|||
|
||||
this.currentElement = clone;
|
||||
this.currentScope = newScope;
|
||||
|
||||
// TODO: prefer the other directive retrieving the controller
|
||||
// by debug mode
|
||||
this.currentController = this.currentElement.children().eq(0).controller(componentName);
|
||||
|
||||
if (this.currentController && this.currentController.$routerOnActivate) {
|
||||
return this.currentController.$routerOnActivate(instruction, previousInstruction);
|
||||
}
|
||||
return $q.when();
|
||||
return this.deferredActivation.promise;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,21 +193,32 @@ function ngOutletFillContentDirective($compile) {
|
|||
link: (scope, element, attrs, ctrl) => {
|
||||
let template = ctrl.$$template;
|
||||
element.html(template);
|
||||
let link = $compile(element.contents());
|
||||
link(scope);
|
||||
|
||||
// TODO: move to primary directive
|
||||
let componentInstance = scope[ctrl.$$componentName];
|
||||
if (componentInstance) {
|
||||
ctrl.$$currentComponent = componentInstance;
|
||||
|
||||
componentInstance.$router = ctrl.$$router;
|
||||
componentInstance.$routeParams = ctrl.$$routeParams;
|
||||
}
|
||||
$compile(element.contents())(scope);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
function routerTriggerDirective($q) {
|
||||
return {
|
||||
require: '^ngOutlet',
|
||||
priority: -1000,
|
||||
link: function(scope, element, attr, ngOutletCtrl) {
|
||||
var promise = $q.when();
|
||||
var outlet = ngOutletCtrl.$$outlet;
|
||||
var currentComponent = outlet.currentController =
|
||||
element.controller(ngOutletCtrl.$$componentName);
|
||||
if (currentComponent.$routerOnActivate) {
|
||||
promise = $q.when(currentComponent.$routerOnActivate(outlet.currentInstruction,
|
||||
outlet.previousInstruction));
|
||||
}
|
||||
promise.then(outlet.deferredActivation.resolve, outlet.deferredActivation.reject);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @name ngLink
|
||||
* @description
|
||||
|
@ -289,7 +293,8 @@ function dashCase(str: string): string {
|
|||
angular.module('ngComponentRouter', [])
|
||||
.directive('ngOutlet', ['$animate', '$q', '$router', ngOutletDirective])
|
||||
.directive('ngOutlet', ['$compile', ngOutletFillContentDirective])
|
||||
.directive('ngLink', ['$router', '$parse', ngLinkDirective]);
|
||||
.directive('ngLink', ['$router', '$parse', ngLinkDirective])
|
||||
.directive('router', ['$q', routerTriggerDirective]);
|
||||
|
||||
/*
|
||||
* A module for inspecting controller constructors
|
||||
|
|
|
@ -116,53 +116,41 @@
|
|||
console.warn('Route for "' + path + '" should use "controllerAs".');
|
||||
}
|
||||
|
||||
var directiveName = routeObjToRouteName(routeCopy, path);
|
||||
var componentName = routeObjToRouteName(routeCopy, path);
|
||||
|
||||
if (!directiveName) {
|
||||
if (!componentName) {
|
||||
throw new Error('Could not determine a name for route "' + path + '".');
|
||||
}
|
||||
|
||||
routeDefinition.component = directiveName;
|
||||
routeDefinition.name = route.name || upperCase(directiveName);
|
||||
routeDefinition.component = componentName;
|
||||
routeDefinition.name = route.name || upperCase(componentName);
|
||||
|
||||
var directiveController = routeCopy.controller;
|
||||
|
||||
var directiveDefinition = {
|
||||
scope: false,
|
||||
var componentDefinition = {
|
||||
controller: directiveController,
|
||||
controllerAs: routeCopy.controllerAs,
|
||||
templateUrl: routeCopy.templateUrl,
|
||||
template: routeCopy.template
|
||||
};
|
||||
controllerAs: routeCopy.controllerAs
|
||||
|
||||
var directiveFactory = function () {
|
||||
return directiveDefinition;
|
||||
};
|
||||
if (routeCopy.templateUrl) componentDefinition.templateUrl = routeCopy.templateUrl;
|
||||
if (routeCopy.template) componentDefinition.template = routeCopy.template;
|
||||
|
||||
|
||||
// if we have route resolve options, prepare a wrapper controller
|
||||
if (directiveController && routeCopy.resolve) {
|
||||
var originalController = directiveController;
|
||||
var resolvedLocals = {};
|
||||
|
||||
directiveDefinition.controller = ['$injector', '$scope', function ($injector, $scope) {
|
||||
componentDefinition.controller = ['$injector', '$scope', function ($injector, $scope) {
|
||||
var locals = angular.extend({
|
||||
$scope: $scope
|
||||
}, resolvedLocals);
|
||||
|
||||
var ctrl = $injector.instantiate(originalController, locals);
|
||||
|
||||
if (routeCopy.controllerAs) {
|
||||
locals.$scope[routeCopy.controllerAs] = ctrl;
|
||||
}
|
||||
|
||||
return ctrl;
|
||||
return $injector.instantiate(originalController, locals);
|
||||
}];
|
||||
|
||||
// we take care of controllerAs in the directive controller wrapper
|
||||
delete directiveDefinition.controllerAs;
|
||||
|
||||
// we resolve the locals in a canActivate block
|
||||
directiveFactory.$canActivate = function() {
|
||||
componentDefinition.$canActivate = function() {
|
||||
var locals = angular.extend({}, routeCopy.resolve);
|
||||
|
||||
angular.forEach(locals, function(value, key) {
|
||||
|
@ -179,7 +167,7 @@
|
|||
}
|
||||
|
||||
// register the dynamically created directive
|
||||
$compileProvider.directive(directiveName, directiveFactory);
|
||||
$compileProvider.component(componentName, componentDefinition);
|
||||
}
|
||||
if (subscriptionFn) {
|
||||
subscriptionFn(routeDefinition);
|
||||
|
|
|
@ -25,7 +25,10 @@ describe('ngOutlet animations', function () {
|
|||
});
|
||||
|
||||
registerComponent('userCmp', {
|
||||
template: '<div>hello {{userCmp.$routeParams.name}}</div>'
|
||||
template: '<div>hello {{userCmp.$routeParams.name}}</div>',
|
||||
$routerOnActivate: function(next) {
|
||||
this.$routeParams = next.params;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -22,7 +22,10 @@ describe('navigation', function () {
|
|||
});
|
||||
|
||||
registerDirective('userCmp', {
|
||||
template: '<div>hello {{userCmp.$routeParams.name}}</div>'
|
||||
template: '<div>hello {{userCmp.$routeParams.name}}</div>',
|
||||
$routerOnActivate: function(next) {
|
||||
this.$routeParams = next.params;
|
||||
}
|
||||
});
|
||||
registerDirective('oneCmp', {
|
||||
template: '<div>{{oneCmp.number}}</div>',
|
||||
|
|
|
@ -95,6 +95,32 @@ describe('router', function () {
|
|||
expect(elt.text()).toBe('Home (true)');
|
||||
}));
|
||||
|
||||
it('should work with a templateUrl component', inject(function($location, $httpBackend) {
|
||||
var $routerOnActivate = jasmine.createSpy('$routerOnActivate');
|
||||
$httpBackend.expectGET('homeCmp.html').respond('Home');
|
||||
registerComponent('homeCmp', {
|
||||
templateUrl: 'homeCmp.html',
|
||||
$routerOnActivate: $routerOnActivate
|
||||
});
|
||||
|
||||
registerComponent('app', {
|
||||
template: '<div ng-outlet></div>',
|
||||
$routeConfig: [
|
||||
{ path: '/', component: 'homeCmp' }
|
||||
]
|
||||
});
|
||||
|
||||
compile('<app></app>');
|
||||
|
||||
$location.path('/');
|
||||
$rootScope.$digest();
|
||||
$httpBackend.flush();
|
||||
var homeElement = elt.find('home-cmp');
|
||||
expect(homeElement.text()).toBe('Home');
|
||||
expect($routerOnActivate).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
|
||||
function registerDirective(name, options) {
|
||||
function factory() {
|
||||
return {
|
||||
|
@ -111,9 +137,15 @@ describe('router', function () {
|
|||
|
||||
var definition = {
|
||||
bindings: options.bindings,
|
||||
template: options.template || '',
|
||||
controller: getController(options),
|
||||
};
|
||||
if (options.template) {
|
||||
definition.template = options.template;
|
||||
}
|
||||
if (options.templateUrl) {
|
||||
definition.templateUrl = options.templateUrl;
|
||||
}
|
||||
|
||||
applyStaticProperties(definition, options);
|
||||
$compileProvider.component(name, definition);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue