Skip to content

Commit

Permalink
fix(upgrade): fix downgrade content projection and injector inheritance
Browse files Browse the repository at this point in the history
- Full support for content projection in downgraded Angular 2
  components. In particular, this enables multi-slot projection and
  other features on <ng-content>.
- Correctly wire up hierarchical injectors for downgraded Angular 2
  components: downgraded components inherit the injector of the first
  other downgraded Angular 2 component they find up the DOM tree.

Closes angular#6629, angular#7727, angular#8729, angular#9643, angular#9649, angular#12675
  • Loading branch information
youdz authored and petebacondarwin committed Dec 8, 2016
1 parent f66728d commit f6c6121
Show file tree
Hide file tree
Showing 11 changed files with 486 additions and 181 deletions.
13 changes: 13 additions & 0 deletions modules/@angular/compiler/src/jit/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ export class JitCompiler implements Compiler {
return this._compileModuleAndAllComponents(moduleType, false).asyncResult;
}

getNgContentSelectors(component: Type<any>): string[] {
const template = this._compiledTemplateCache.get(component);
if (!template) {
throw new Error(`The component ${stringify(component)} is not yet compiled!`);
}
return template.compMeta.template.ngContentSelectors;
}

private _compileModuleAndComponents<T>(moduleType: Type<T>, isSync: boolean):
SyncAsyncResult<NgModuleFactory<T>> {
const loadingPromise = this._loadModules(moduleType, isSync);
Expand Down Expand Up @@ -408,6 +416,11 @@ class ModuleBoundCompiler implements Compiler {
return this._delegate.compileModuleAndAllComponentsAsync(moduleType);
}

getNgContentSelectors(component: Type<any>): string[] {
return this._delegate.getNgContentSelectors(component);
}


/**
* Clears all caches
*/
Expand Down
4 changes: 4 additions & 0 deletions modules/@angular/compiler/testing/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ export class TestingCompilerImpl implements TestingCompiler {
return this._compiler.compileModuleAndAllComponentsAsync(moduleType);
}

getNgContentSelectors(component: Type<any>): string[] {
return this._compiler.getNgContentSelectors(component);
}

overrideModule(ngModule: Type<any>, override: MetadataOverride<NgModule>): void {
const oldMetadata = this._moduleResolver.resolve(ngModule, false);
this._moduleResolver.setNgModule(
Expand Down
8 changes: 8 additions & 0 deletions modules/@angular/core/src/linker/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ export class Compiler {
throw _throwError();
}

/**
* Exposes the CSS-style selectors that have been used in `ngContent` directives within
* the template of the given component.
* This is used by the `upgrade` library to compile the appropriate transclude content
* in the Angular 1 wrapper component.
*/
getNgContentSelectors(component: Type<any>): string[] { throw _throwError(); }

/**
* Clears all caches.
*/
Expand Down
2 changes: 1 addition & 1 deletion modules/@angular/upgrade/src/angular_js.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export interface IModule {
run(a: IInjectable): IModule;
}
export interface ICompileService {
(element: Element|NodeList|string, transclude?: Function): ILinkFn;
(element: Element|NodeList|Node[]|string, transclude?: Function): ILinkFn;
}
export interface ILinkFn {
(scope: IScope, cloneAttachFn?: ICloneAttachFunction, options?: ILinkFnOptions): IAugmentedJQuery;
Expand Down
2 changes: 1 addition & 1 deletion modules/@angular/upgrade/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ export const NG1_INJECTOR = '$injector';
export const NG1_PARSE = '$parse';
export const NG1_TEMPLATE_CACHE = '$templateCache';
export const NG1_TESTABILITY = '$$testability';
export const REQUIRE_INJECTOR = '?^' + NG2_INJECTOR;
export const REQUIRE_INJECTOR = '?^^' + NG2_INJECTOR;
23 changes: 4 additions & 19 deletions modules/@angular/upgrade/src/downgrade_ng2_adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,21 @@ export class DowngradeNg2ComponentAdapter {
componentRef: ComponentRef<any> = null;
changeDetector: ChangeDetectorRef = null;
componentScope: angular.IScope;
childNodes: Node[];
contentInsertionPoint: Node = null;

constructor(
private id: string, private info: ComponentInfo, private element: angular.IAugmentedJQuery,
private info: ComponentInfo, private element: angular.IAugmentedJQuery,
private attrs: angular.IAttributes, private scope: angular.IScope,
private parentInjector: Injector, private parse: angular.IParseService,
private componentFactory: ComponentFactory<any>) {
(<any>this.element[0]).id = id;
this.componentScope = scope.$new();
this.childNodes = <Node[]><any>element.contents();
}

bootstrapNg2() {
bootstrapNg2(projectableNodes: Node[][]) {
const childInjector = ReflectiveInjector.resolveAndCreate(
[{provide: NG1_SCOPE, useValue: this.componentScope}], this.parentInjector);
this.contentInsertionPoint = document.createComment('ng1 insertion point');

this.componentRef = this.componentFactory.create(
childInjector, [[this.contentInsertionPoint]], this.element[0]);
this.componentRef =
this.componentFactory.create(childInjector, projectableNodes, this.element[0]);
this.changeDetector = this.componentRef.changeDetectorRef;
this.component = this.componentRef.instance;
}
Expand Down Expand Up @@ -103,16 +98,6 @@ export class DowngradeNg2ComponentAdapter {
this.componentScope.$watch(() => this.changeDetector && this.changeDetector.detectChanges());
}

projectContent() {
const childNodes = this.childNodes;
const parent = this.contentInsertionPoint.parentNode;
if (parent) {
for (let i = 0, ii = childNodes.length; i < ii; i++) {
parent.insertBefore(childNodes[i], this.contentInsertionPoint);
}
}
}

setupOutputs() {
const attrs = this.attrs;
const outputs = this.info.outputs || [];
Expand Down
Loading

0 comments on commit f6c6121

Please sign in to comment.