fix(upgrade): fallback to root ng2 injector when element is compiled outside the document (#8684)
Currently downgraded ng2 elements fail inside a ui-router view because they are unable to require an ng2 Injector via the require attribute of the DDO, because ui-router compiles its templates before they are inserted in a ui-view. This adds a "fallback" behavior if a parent injector cannot be found to go to the root ng2 Injector.
This commit is contained in:
parent
7bb5167239
commit
db8290632f
|
@ -12,4 +12,4 @@ export const NG1_INJECTOR = '$injector';
|
||||||
export const NG1_PARSE = '$parse';
|
export const NG1_PARSE = '$parse';
|
||||||
export const NG1_TEMPLATE_CACHE = '$templateCache';
|
export const NG1_TEMPLATE_CACHE = '$templateCache';
|
||||||
export const NG1_TESTABILITY = '$$testability';
|
export const NG1_TESTABILITY = '$$testability';
|
||||||
export const REQUIRE_INJECTOR = '^' + NG2_INJECTOR;
|
export const REQUIRE_INJECTOR = '?^' + NG2_INJECTOR;
|
||||||
|
|
|
@ -42,7 +42,7 @@ export class DowngradeNg2ComponentAdapter {
|
||||||
this.contentInsertionPoint = document.createComment('ng1 insertion point');
|
this.contentInsertionPoint = document.createComment('ng1 insertion point');
|
||||||
|
|
||||||
this.componentRef =
|
this.componentRef =
|
||||||
this.componentFactory.create(childInjector, [[this.contentInsertionPoint]], '#' + this.id);
|
this.componentFactory.create(childInjector, [[this.contentInsertionPoint]], this.element[0]);
|
||||||
this.changeDetector = this.componentRef.changeDetectorRef;
|
this.changeDetector = this.componentRef.changeDetectorRef;
|
||||||
this.component = this.componentRef.instance;
|
this.component = this.componentRef.instance;
|
||||||
}
|
}
|
||||||
|
|
|
@ -540,8 +540,9 @@ interface ComponentFactoryRefMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
function ng1ComponentDirective(info: ComponentInfo, idPrefix: string): Function {
|
function ng1ComponentDirective(info: ComponentInfo, idPrefix: string): Function {
|
||||||
(<any>directiveFactory).$inject = [NG2_COMPONENT_FACTORY_REF_MAP, NG1_PARSE];
|
(<any>directiveFactory).$inject = [NG1_INJECTOR, NG2_COMPONENT_FACTORY_REF_MAP, NG1_PARSE];
|
||||||
function directiveFactory(componentFactoryRefMap: ComponentFactoryRefMap,
|
function directiveFactory(ng1Injector: angular.IInjectorService,
|
||||||
|
componentFactoryRefMap: ComponentFactoryRefMap,
|
||||||
parse: angular.IParseService): angular.IDirective {
|
parse: angular.IParseService): angular.IDirective {
|
||||||
var componentFactory: ComponentFactory<any> = componentFactoryRefMap[info.selector];
|
var componentFactory: ComponentFactory<any> = componentFactoryRefMap[info.selector];
|
||||||
if (!componentFactory) throw new Error('Expecting ComponentFactory for: ' + info.selector);
|
if (!componentFactory) throw new Error('Expecting ComponentFactory for: ' + info.selector);
|
||||||
|
@ -553,6 +554,9 @@ function ng1ComponentDirective(info: ComponentInfo, idPrefix: string): Function
|
||||||
post: (scope: angular.IScope, element: angular.IAugmentedJQuery, attrs: angular.IAttributes,
|
post: (scope: angular.IScope, element: angular.IAugmentedJQuery, attrs: angular.IAttributes,
|
||||||
parentInjector: any, transclude: angular.ITranscludeFunction): void => {
|
parentInjector: any, transclude: angular.ITranscludeFunction): void => {
|
||||||
var domElement = <any>element[0];
|
var domElement = <any>element[0];
|
||||||
|
if (parentInjector === null) {
|
||||||
|
parentInjector = ng1Injector.get(NG2_INJECTOR);
|
||||||
|
}
|
||||||
var facade =
|
var facade =
|
||||||
new DowngradeNg2ComponentAdapter(idPrefix + (idCount++), info, element, attrs, scope,
|
new DowngradeNg2ComponentAdapter(idPrefix + (idCount++), info, element, attrs, scope,
|
||||||
<Injector>parentInjector, parse, componentFactory);
|
<Injector>parentInjector, parse, componentFactory);
|
||||||
|
|
|
@ -256,6 +256,37 @@ export function main() {
|
||||||
async.done();
|
async.done();
|
||||||
})});
|
})});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
it('should fallback to the root ng2.injector when compiled outside the dom',
|
||||||
|
inject([AsyncTestCompleter], (async) => {
|
||||||
|
var adapter: UpgradeAdapter = new UpgradeAdapter();
|
||||||
|
var ng1Module = angular.module('ng1', []);
|
||||||
|
|
||||||
|
ng1Module.directive('ng1', ['$compile', ($compile) => {
|
||||||
|
return {
|
||||||
|
link: function($scope, $element, $attrs) {
|
||||||
|
var compiled = $compile("<ng2></ng2>");
|
||||||
|
var template = compiled($scope);
|
||||||
|
$element.append(template);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}]);
|
||||||
|
|
||||||
|
var Ng2 = Component({ selector: 'ng2', template: 'test' })
|
||||||
|
.Class({
|
||||||
|
constructor: function() { }
|
||||||
|
});
|
||||||
|
ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2));
|
||||||
|
var element = html('<ng1></ng1>');
|
||||||
|
adapter.bootstrap(element, ['ng1'])
|
||||||
|
.ready((ref) => {
|
||||||
|
expect(multiTrim(document.body.textContent))
|
||||||
|
.toEqual('test');
|
||||||
|
ref.dispose();
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('upgrade ng1 component', () => {
|
describe('upgrade ng1 component', () => {
|
||||||
|
|
Loading…
Reference in New Issue