diff --git a/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts b/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts index 7912501877..74edd68032 100644 --- a/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts +++ b/packages/compiler-cli/test/compliance/r3_compiler_compliance_spec.ts @@ -1144,6 +1144,7 @@ describe('compiler compliance', () => { type: SimpleComponent, selectors: [["simple"]], factory: function SimpleComponent_Factory(t) { return new (t || SimpleComponent)(); }, + ngContentSelectors: _c0, consts: 2, vars: 0, template: function SimpleComponent_Template(rf, ctx) { @@ -1167,6 +1168,7 @@ describe('compiler compliance', () => { type: ComplexComponent, selectors: [["complex"]], factory: function ComplexComponent_Factory(t) { return new (t || ComplexComponent)(); }, + ngContentSelectors: _c4, consts: 4, vars: 0, template: function ComplexComponent_Template(rf, ctx) { @@ -1561,6 +1563,7 @@ describe('compiler compliance', () => { ($r3$.ɵqueryRefresh(($tmp$ = $r3$.ɵloadQueryList(queryStartIndex))) && ($instance$.someDir = $tmp$.first)); ($r3$.ɵqueryRefresh(($tmp$ = $r3$.ɵloadQueryList((queryStartIndex + 1)))) && ($instance$.someDirList = $tmp$)); }, + ngContentSelectors: _c0, consts: 2, vars: 0, template: function ContentQueryComponent_Template(rf, ctx) { diff --git a/packages/compiler/src/render3/view/compiler.ts b/packages/compiler/src/render3/view/compiler.ts index a326749a94..c329ccc2f9 100644 --- a/packages/compiler/src/render3/view/compiler.ts +++ b/packages/compiler/src/render3/view/compiler.ts @@ -264,6 +264,13 @@ export function compileComponentFromMetadata( const templateFunctionExpression = templateBuilder.buildTemplateFunction(template.nodes, []); + // We need to provide this so that dynamically generated components know what + // projected content blocks to pass through to the component when it is instantiated. + const ngContentSelectors = templateBuilder.getNgContentSelectors(); + if (ngContentSelectors) { + definitionMap.set('ngContentSelectors', ngContentSelectors); + } + // e.g. `consts: 2` definitionMap.set('consts', o.literal(templateBuilder.getConstCount())); diff --git a/packages/compiler/src/render3/view/template.ts b/packages/compiler/src/render3/view/template.ts index fb94119dfe..4ebd220376 100644 --- a/packages/compiler/src/render3/view/template.ts +++ b/packages/compiler/src/render3/view/template.ts @@ -915,6 +915,12 @@ export class TemplateDefinitionBuilder implements t.Visitor, LocalResolver getVarCount() { return this._pureFunctionSlots; } + getNgContentSelectors(): o.Expression|null { + return this._hasNgContent ? + this.constantPool.getConstLiteral(asLiteral(this._ngContentSelectors), true) : + null; + } + private bindingContext() { return `${this._bindingContext++}`; } // Bindings must only be resolved after all local refs have been visited, so all diff --git a/packages/core/src/render3/component_ref.ts b/packages/core/src/render3/component_ref.ts index fc293f5d2e..cd571131c1 100644 --- a/packages/core/src/render3/component_ref.ts +++ b/packages/core/src/render3/component_ref.ts @@ -119,7 +119,10 @@ export class ComponentFactory extends viewEngine_ComponentFactory { super(); this.componentType = componentDef.type; this.selector = componentDef.selectors[0][0] as string; - this.ngContentSelectors = []; + // The component definition does not include the wildcard ('*') selector in its list. + // It is implicitly expected as the first item in the projectable nodes array. + this.ngContentSelectors = + componentDef.ngContentSelectors ? ['*', ...componentDef.ngContentSelectors] : []; } create( diff --git a/packages/core/src/render3/definition.ts b/packages/core/src/render3/definition.ts index 3d1d0d3aea..dc6b0bd9da 100644 --- a/packages/core/src/render3/definition.ts +++ b/packages/core/src/render3/definition.ts @@ -182,6 +182,11 @@ export function defineComponent(componentDefinition: { */ template: ComponentTemplate; + /** + * An array of `ngContent[selector]` values that were found in the template. + */ + ngContentSelectors?: string[]; + /** * Additional set of instructions specific to view query processing. This could be seen as a * set of instruction to be inserted into the template function. @@ -249,6 +254,7 @@ export function defineComponent(componentDefinition: { vars: componentDefinition.vars, factory: componentDefinition.factory, template: componentDefinition.template || null !, + ngContentSelectors: componentDefinition.ngContentSelectors, hostBindings: componentDefinition.hostBindings || null, contentQueries: componentDefinition.contentQueries || null, contentQueriesRefresh: componentDefinition.contentQueriesRefresh || null, diff --git a/packages/core/src/render3/interfaces/definition.ts b/packages/core/src/render3/interfaces/definition.ts index 2c3570c48f..585cf49d69 100644 --- a/packages/core/src/render3/interfaces/definition.ts +++ b/packages/core/src/render3/interfaces/definition.ts @@ -189,6 +189,11 @@ export interface ComponentDef extends DirectiveDef { */ readonly template: ComponentTemplate; + /** + * An array of `ngContent[selector]` values that were found in the template. + */ + readonly ngContentSelectors?: string[]; + /** * A set of styles that the component needs to be present for component to render correctly. */ diff --git a/packages/core/test/render3/component_ref_spec.ts b/packages/core/test/render3/component_ref_spec.ts index 8b832a912e..963e7ab70c 100644 --- a/packages/core/test/render3/component_ref_spec.ts +++ b/packages/core/test/render3/component_ref_spec.ts @@ -18,7 +18,28 @@ describe('ComponentFactory', () => { const cfr = injectComponentFactoryResolver(); describe('constructor()', () => { - it('should correctly populate public properties', () => { + it('should correctly populate default properties', () => { + class TestComponent { + static ngComponentDef = defineComponent({ + type: TestComponent, + selectors: [['test', 'foo'], ['bar']], + consts: 0, + vars: 0, + template: () => undefined, + factory: () => new TestComponent(), + }); + } + + const cf = cfr.resolveComponentFactory(TestComponent); + + expect(cf.selector).toBe('test'); + expect(cf.componentType).toBe(TestComponent); + expect(cf.ngContentSelectors).toEqual([]); + expect(cf.inputs).toEqual([]); + expect(cf.outputs).toEqual([]); + }); + + it('should correctly populate defined properties', () => { class TestComponent { static ngComponentDef = defineComponent({ type: TestComponent, @@ -27,6 +48,7 @@ describe('ComponentFactory', () => { consts: 0, vars: 0, template: () => undefined, + ngContentSelectors: ['a', 'b'], factory: () => new TestComponent(), inputs: { in1: 'in1', @@ -42,7 +64,7 @@ describe('ComponentFactory', () => { const cf = cfr.resolveComponentFactory(TestComponent); expect(cf.componentType).toBe(TestComponent); - expect(cf.ngContentSelectors).toEqual([]); + expect(cf.ngContentSelectors).toEqual(['*', 'a', 'b']); expect(cf.selector).toBe('test'); expect(cf.inputs).toEqual([ diff --git a/packages/upgrade/test/dynamic/upgrade_spec.ts b/packages/upgrade/test/dynamic/upgrade_spec.ts index 58de0e9494..eae2a62923 100644 --- a/packages/upgrade/test/dynamic/upgrade_spec.ts +++ b/packages/upgrade/test/dynamic/upgrade_spec.ts @@ -30,31 +30,30 @@ withEachNg1Version(() => { describe('(basic use)', () => { it('should have AngularJS loaded', () => expect(angular.version.major).toBe(1)); - fixmeIvy('FW-714: ng1 projected content is not being rendered') - .it('should instantiate ng2 in ng1 template and project content', async(() => { - const ng1Module = angular.module('ng1', []); + it('should instantiate ng2 in ng1 template and project content', async(() => { + const ng1Module = angular.module('ng1', []); - @Component({ - selector: 'ng2', - template: `{{ 'NG2' }}()`, - }) - class Ng2 { - } + @Component({ + selector: 'ng2', + template: `{{ 'NG2' }}()`, + }) + class Ng2 { + } - @NgModule({declarations: [Ng2], imports: [BrowserModule]}) - class Ng2Module { - } + @NgModule({declarations: [Ng2], imports: [BrowserModule]}) + class Ng2Module { + } - const element = - html('
{{ \'ng1[\' }}~{{ \'ng-content\' }}~{{ \']\' }}
'); + const element = + html('
{{ \'ng1[\' }}~{{ \'ng-content\' }}~{{ \']\' }}
'); - const adapter: UpgradeAdapter = new UpgradeAdapter(Ng2Module); - ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); - adapter.bootstrap(element, ['ng1']).ready((ref) => { - expect(document.body.textContent).toEqual('ng1[NG2(~ng-content~)]'); - ref.dispose(); - }); - })); + const adapter: UpgradeAdapter = new UpgradeAdapter(Ng2Module); + ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); + adapter.bootstrap(element, ['ng1']).ready((ref) => { + expect(document.body.textContent).toEqual('ng1[NG2(~ng-content~)]'); + ref.dispose(); + }); + })); it('should instantiate ng1 in ng2 template and project content', async(() => { const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); @@ -724,72 +723,68 @@ withEachNg1Version(() => { }); })); - fixmeIvy('FW-714: ng1 projected content is not being rendered') - .it('should support multi-slot projection', async(() => { - const ng1Module = angular.module('ng1', []); + it('should support multi-slot projection', async(() => { + const ng1Module = angular.module('ng1', []); - @Component({ - selector: 'ng2', - template: '2a()' + - '2b()' - }) - class Ng2 { - } + @Component({ + selector: 'ng2', + template: '2a()' + + '2b()' + }) + class Ng2 { + } - @NgModule({declarations: [Ng2], imports: [BrowserModule]}) - class Ng2Module { - } + @NgModule({declarations: [Ng2], imports: [BrowserModule]}) + class Ng2Module { + } - // The ng-if on one of the projected children is here to make sure - // the correct slot is targeted even with structural directives in play. - const element = html( - '
1a
1b
'); + // The ng-if on one of the projected children is here to make sure + // the correct slot is targeted even with structural directives in play. + const element = html( + '
1a
1b
'); - const adapter: UpgradeAdapter = new UpgradeAdapter(Ng2Module); - ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); - adapter.bootstrap(element, ['ng1']).ready((ref) => { - expect(document.body.textContent).toEqual('2a(1a)2b(1b)'); - ref.dispose(); - }); - })); + const adapter: UpgradeAdapter = new UpgradeAdapter(Ng2Module); + ng1Module.directive('ng2', adapter.downgradeNg2Component(Ng2)); + adapter.bootstrap(element, ['ng1']).ready((ref) => { + expect(document.body.textContent).toEqual('2a(1a)2b(1b)'); + ref.dispose(); + }); + })); - fixmeIvy('FW-714: ng1 projected content is not being rendered') - .it('should correctly project structural directives', async(() => { - @Component( - {selector: 'ng2', template: 'ng2-{{ itemId }}()'}) - class Ng2Component { - // TODO(issue/24571): remove '!'. - @Input() itemId !: string; - } + it('should correctly project structural directives', async(() => { + @Component({selector: 'ng2', template: 'ng2-{{ itemId }}()'}) + class Ng2Component { + // TODO(issue/24571): remove '!'. + @Input() itemId !: string; + } - @NgModule({imports: [BrowserModule], declarations: [Ng2Component]}) - class Ng2Module { - } + @NgModule({imports: [BrowserModule], declarations: [Ng2Component]}) + class Ng2Module { + } - const adapter: UpgradeAdapter = new UpgradeAdapter(Ng2Module); - const ng1Module = - angular.module('ng1', []) - .directive('ng2', adapter.downgradeNg2Component(Ng2Component)) - .run(($rootScope: angular.IRootScopeService) => { - $rootScope['items'] = [ - {id: 'a', subitems: [1, 2, 3]}, {id: 'b', subitems: [4, 5, 6]}, - {id: 'c', subitems: [7, 8, 9]} - ]; - }); + const adapter: UpgradeAdapter = new UpgradeAdapter(Ng2Module); + const ng1Module = angular.module('ng1', []) + .directive('ng2', adapter.downgradeNg2Component(Ng2Component)) + .run(($rootScope: angular.IRootScopeService) => { + $rootScope['items'] = [ + {id: 'a', subitems: [1, 2, 3]}, {id: 'b', subitems: [4, 5, 6]}, + {id: 'c', subitems: [7, 8, 9]} + ]; + }); - const element = html(` + const element = html(`
{{ subitem }}
`); - adapter.bootstrap(element, [ng1Module.name]).ready(ref => { - expect(multiTrim(document.body.textContent)) - .toBe('ng2-a( 123 )ng2-b( 456 )ng2-c( 789 )'); - ref.dispose(); - }); - })); + adapter.bootstrap(element, [ng1Module.name]).ready(ref => { + expect(multiTrim(document.body.textContent)) + .toBe('ng2-a( 123 )ng2-b( 456 )ng2-c( 789 )'); + ref.dispose(); + }); + })); it('should allow attribute selectors for components in ng2', async(() => { const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => MyNg2Module)); @@ -3110,7 +3105,7 @@ withEachNg1Version(() => { }); })); - fixmeIvy('FW-714: ng1 projected content is not being rendered') + fixmeIvy('FW-873: projected component injector hierarchy not wired up correctly') .it('should respect hierarchical dependency injection for ng2', async(() => { const ng1Module = angular.module('ng1', []); @@ -3213,45 +3208,44 @@ withEachNg1Version(() => { }); describe('examples', () => { - fixmeIvy('FW-714: ng1 projected content is not being rendered') - .it('should verify UpgradeAdapter example', async(() => { - const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); - const module = angular.module('myExample', []); + it('should verify UpgradeAdapter example', async(() => { + const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); + const module = angular.module('myExample', []); - const ng1 = () => { - return { - scope: {title: '='}, - transclude: true, - template: 'ng1[Hello {{title}}!]()' - }; - }; - module.directive('ng1', ng1); + const ng1 = () => { + return { + scope: {title: '='}, + transclude: true, + template: 'ng1[Hello {{title}}!]()' + }; + }; + module.directive('ng1', ng1); - @Component({ - selector: 'ng2', - inputs: ['name'], - template: 'ng2[transclude]()' - }) - class Ng2 { - } + @Component({ + selector: 'ng2', + inputs: ['name'], + template: 'ng2[transclude]()' + }) + class Ng2 { + } - @NgModule({ - declarations: [adapter.upgradeNg1Component('ng1'), Ng2], - imports: [BrowserModule], - }) - class Ng2Module { - } + @NgModule({ + declarations: [adapter.upgradeNg1Component('ng1'), Ng2], + imports: [BrowserModule], + }) + class Ng2Module { + } - module.directive('ng2', adapter.downgradeNg2Component(Ng2)); + module.directive('ng2', adapter.downgradeNg2Component(Ng2)); - document.body.innerHTML = 'project'; + document.body.innerHTML = 'project'; - adapter.bootstrap(document.body.firstElementChild !, ['myExample']).ready((ref) => { - expect(multiTrim(document.body.textContent)) - .toEqual('ng2[ng1[Hello World!](transclude)](project)'); - ref.dispose(); - }); - })); + adapter.bootstrap(document.body.firstElementChild !, ['myExample']).ready((ref) => { + expect(multiTrim(document.body.textContent)) + .toEqual('ng2[ng1[Hello World!](transclude)](project)'); + ref.dispose(); + }); + })); }); describe('registerForNg1Tests', () => { diff --git a/packages/upgrade/test/static/integration/content_projection_spec.ts b/packages/upgrade/test/static/integration/content_projection_spec.ts index b385dec9c1..296cbffb7b 100644 --- a/packages/upgrade/test/static/integration/content_projection_spec.ts +++ b/packages/upgrade/test/static/integration/content_projection_spec.ts @@ -22,82 +22,78 @@ withEachNg1Version(() => { beforeEach(() => destroyPlatform()); afterEach(() => destroyPlatform()); - fixmeIvy('FW-714: ng1 projected content is not being rendered') - .it('should instantiate ng2 in ng1 template and project content', async(() => { + it('should instantiate ng2 in ng1 template and project content', async(() => { - // the ng2 component that will be used in ng1 (downgraded) - @Component({selector: 'ng2', template: `{{ prop }}()`}) - class Ng2Component { - prop = 'NG2'; - ngContent = 'ng2-content'; - } + // the ng2 component that will be used in ng1 (downgraded) + @Component({selector: 'ng2', template: `{{ prop }}()`}) + class Ng2Component { + prop = 'NG2'; + ngContent = 'ng2-content'; + } - // our upgrade module to host the component to downgrade - @NgModule({ - imports: [BrowserModule, UpgradeModule], - declarations: [Ng2Component], - entryComponents: [Ng2Component] - }) - class Ng2Module { - ngDoBootstrap() {} - } + // our upgrade module to host the component to downgrade + @NgModule({ + imports: [BrowserModule, UpgradeModule], + declarations: [Ng2Component], + entryComponents: [Ng2Component] + }) + class Ng2Module { + ngDoBootstrap() {} + } - // the ng1 app module that will consume the downgraded component - const ng1Module = angular - .module('ng1', []) - // create an ng1 facade of the ng2 component - .directive('ng2', downgradeComponent({component: Ng2Component})) - .run(($rootScope: angular.IRootScopeService) => { - $rootScope['prop'] = 'NG1'; - $rootScope['ngContent'] = 'ng1-content'; - }); + // the ng1 app module that will consume the downgraded component + const ng1Module = angular + .module('ng1', []) + // create an ng1 facade of the ng2 component + .directive('ng2', downgradeComponent({component: Ng2Component})) + .run(($rootScope: angular.IRootScopeService) => { + $rootScope['prop'] = 'NG1'; + $rootScope['ngContent'] = 'ng1-content'; + }); - const element = - html('
{{ \'ng1[\' }}~{{ ngContent }}~{{ \']\' }}
'); + const element = html('
{{ \'ng1[\' }}~{{ ngContent }}~{{ \']\' }}
'); - bootstrap(platformBrowserDynamic(), Ng2Module, element, ng1Module).then((upgrade) => { - expect(document.body.textContent).toEqual('ng1[NG2(~ng1-content~)]'); - }); - })); + bootstrap(platformBrowserDynamic(), Ng2Module, element, ng1Module).then((upgrade) => { + expect(document.body.textContent).toEqual('ng1[NG2(~ng1-content~)]'); + }); + })); - fixmeIvy('FW-714: ng1 projected content is not being rendered') - .it('should correctly project structural directives', async(() => { - @Component({selector: 'ng2', template: 'ng2-{{ itemId }}()'}) - class Ng2Component { - // TODO(issue/24571): remove '!'. - @Input() itemId !: string; - } + it('should correctly project structural directives', async(() => { + @Component({selector: 'ng2', template: 'ng2-{{ itemId }}()'}) + class Ng2Component { + // TODO(issue/24571): remove '!'. + @Input() itemId !: string; + } - @NgModule({ - imports: [BrowserModule, UpgradeModule], - declarations: [Ng2Component], - entryComponents: [Ng2Component] - }) - class Ng2Module { - ngDoBootstrap() {} - } + @NgModule({ + imports: [BrowserModule, UpgradeModule], + declarations: [Ng2Component], + entryComponents: [Ng2Component] + }) + class Ng2Module { + ngDoBootstrap() {} + } - const ng1Module = - angular.module('ng1', []) - .directive('ng2', downgradeComponent({component: Ng2Component})) - .run(($rootScope: angular.IRootScopeService) => { - $rootScope['items'] = [ - {id: 'a', subitems: [1, 2, 3]}, {id: 'b', subitems: [4, 5, 6]}, - {id: 'c', subitems: [7, 8, 9]} - ]; - }); + const ng1Module = angular.module('ng1', []) + .directive('ng2', downgradeComponent({component: Ng2Component})) + .run(($rootScope: angular.IRootScopeService) => { + $rootScope['items'] = [ + {id: 'a', subitems: [1, 2, 3]}, {id: 'b', subitems: [4, 5, 6]}, + {id: 'c', subitems: [7, 8, 9]} + ]; + }); - const element = html(` + const element = html(`
{{ subitem }}
`); - bootstrap(platformBrowserDynamic(), Ng2Module, element, ng1Module).then(upgrade => { - expect(multiTrim(document.body.textContent)) - .toBe('ng2-a( 123 )ng2-b( 456 )ng2-c( 789 )'); - }); - })); + bootstrap(platformBrowserDynamic(), Ng2Module, element, ng1Module).then(upgrade => { + expect(multiTrim(document.body.textContent)) + .toBe('ng2-a( 123 )ng2-b( 456 )ng2-c( 789 )'); + }); + })); it('should instantiate ng1 in ng2 template and project content', async(() => { @@ -145,39 +141,38 @@ withEachNg1Version(() => { }); })); - fixmeIvy('FW-714: ng1 projected content is not being rendered') - .it('should support multi-slot projection', async(() => { + it('should support multi-slot projection', async(() => { - @Component({ - selector: 'ng2', - template: '2a()' + - '2b()' - }) - class Ng2Component { - constructor() {} - } + @Component({ + selector: 'ng2', + template: '2a()' + + '2b()' + }) + class Ng2Component { + constructor() {} + } - @NgModule({ - declarations: [Ng2Component], - entryComponents: [Ng2Component], - imports: [BrowserModule, UpgradeModule] - }) - class Ng2Module { - ngDoBootstrap() {} - } + @NgModule({ + declarations: [Ng2Component], + entryComponents: [Ng2Component], + imports: [BrowserModule, UpgradeModule] + }) + class Ng2Module { + ngDoBootstrap() {} + } - const ng1Module = angular.module('ng1', []).directive( - 'ng2', downgradeComponent({component: Ng2Component})); + const ng1Module = angular.module('ng1', []).directive( + 'ng2', downgradeComponent({component: Ng2Component})); - // The ng-if on one of the projected children is here to make sure - // the correct slot is targeted even with structural directives in play. - const element = html( - '
1a
1b
'); + // The ng-if on one of the projected children is here to make sure + // the correct slot is targeted even with structural directives in play. + const element = html( + '
1a
1b
'); - bootstrap(platformBrowserDynamic(), Ng2Module, element, ng1Module).then((upgrade) => { - expect(document.body.textContent).toEqual('2a(1a)2b(1b)'); - }); - })); + bootstrap(platformBrowserDynamic(), Ng2Module, element, ng1Module).then((upgrade) => { + expect(document.body.textContent).toEqual('2a(1a)2b(1b)'); + }); + })); }); }); diff --git a/packages/upgrade/test/static/integration/downgrade_component_spec.ts b/packages/upgrade/test/static/integration/downgrade_component_spec.ts index 73b140a510..36c2fd9bc7 100644 --- a/packages/upgrade/test/static/integration/downgrade_component_spec.ts +++ b/packages/upgrade/test/static/integration/downgrade_component_spec.ts @@ -709,7 +709,7 @@ withEachNg1Version(() => { }); })); - fixmeIvy('FW-714: ng1 projected content is not being rendered') + fixmeIvy('FW-873: projected component injector hierarchy not wired up correctly') .it('should respect hierarchical dependency injection for ng2', async(() => { @Component({selector: 'parent', template: 'parent()'}) class ParentComponent { diff --git a/packages/upgrade/test/static/integration/downgrade_module_spec.ts b/packages/upgrade/test/static/integration/downgrade_module_spec.ts index 6d0fd93ef7..8dcb06bd80 100644 --- a/packages/upgrade/test/static/integration/downgrade_module_spec.ts +++ b/packages/upgrade/test/static/integration/downgrade_module_spec.ts @@ -952,7 +952,6 @@ withEachNg1Version(() => { })); fixmeIvy('FW-715: ngOnChanges being called a second time unexpectedly') - .fixmeIvy('FW-714: ng1 projected content is not being rendered') .it('should run the lifecycle hooks in the correct order', async(() => { const logs: string[] = []; let rootScope: angular.IRootScopeService; diff --git a/packages/upgrade/test/static/integration/examples_spec.ts b/packages/upgrade/test/static/integration/examples_spec.ts index 90b66a88fa..dae47a45c9 100644 --- a/packages/upgrade/test/static/integration/examples_spec.ts +++ b/packages/upgrade/test/static/integration/examples_spec.ts @@ -24,70 +24,69 @@ withEachNg1Version(() => { it('should have AngularJS loaded', () => expect(angular.version.major).toBe(1)); - fixmeIvy('FW-714: ng1 projected content is not being rendered') - .it('should verify UpgradeAdapter example', async(() => { + it('should verify UpgradeAdapter example', async(() => { - // This is wrapping (upgrading) an AngularJS component to be used in an Angular - // component - @Directive({selector: 'ng1'}) - class Ng1Component extends UpgradeComponent { - // TODO(issue/24571): remove '!'. - @Input() title !: string; + // This is wrapping (upgrading) an AngularJS component to be used in an Angular + // component + @Directive({selector: 'ng1'}) + class Ng1Component extends UpgradeComponent { + // TODO(issue/24571): remove '!'. + @Input() title !: string; - constructor(elementRef: ElementRef, injector: Injector) { - super('ng1', elementRef, injector); - } - } + constructor(elementRef: ElementRef, injector: Injector) { + super('ng1', elementRef, injector); + } + } - // This is an Angular component that will be downgraded - @Component({ - selector: 'ng2', - template: 'ng2[transclude]()' - }) - class Ng2Component { - // TODO(issue/24571): remove '!'. - @Input('name') nameProp !: string; - } + // This is an Angular component that will be downgraded + @Component({ + selector: 'ng2', + template: 'ng2[transclude]()' + }) + class Ng2Component { + // TODO(issue/24571): remove '!'. + @Input('name') nameProp !: string; + } - // This module represents the Angular pieces of the application - @NgModule({ - declarations: [Ng1Component, Ng2Component], - entryComponents: [Ng2Component], - imports: [BrowserModule, UpgradeModule] - }) - class Ng2Module { - ngDoBootstrap() { /* this is a placeholder to stop the bootstrapper from - complaining */ - } - } + // This module represents the Angular pieces of the application + @NgModule({ + declarations: [Ng1Component, Ng2Component], + entryComponents: [Ng2Component], + imports: [BrowserModule, UpgradeModule] + }) + class Ng2Module { + ngDoBootstrap() { /* this is a placeholder to stop the bootstrapper from + complaining */ + } + } - // This module represents the AngularJS pieces of the application - const ng1Module = - angular - .module('myExample', []) - // This is an AngularJS component that will be upgraded - .directive( - 'ng1', - () => { - return { - scope: {title: '='}, - transclude: true, - template: 'ng1[Hello {{title}}!]()' - }; - }) - // This is wrapping (downgrading) an Angular component to be used in - // AngularJS - .directive('ng2', downgradeComponent({component: Ng2Component})); + // This module represents the AngularJS pieces of the application + const ng1Module = + angular + .module('myExample', []) + // This is an AngularJS component that will be upgraded + .directive( + 'ng1', + () => { + return { + scope: {title: '='}, + transclude: true, + template: 'ng1[Hello {{title}}!]()' + }; + }) + // This is wrapping (downgrading) an Angular component to be used in + // AngularJS + .directive('ng2', downgradeComponent({component: Ng2Component})); - // This is the (AngularJS) application bootstrap element - // Notice that it is actually a downgraded Angular component - const element = html('project'); + // This is the (AngularJS) application bootstrap element + // Notice that it is actually a downgraded Angular component + const element = html('project'); - // Let's use a helper function to make this simpler - bootstrap(platformBrowserDynamic(), Ng2Module, element, ng1Module).then(upgrade => { - expect(multiTrim(element.textContent)) - .toBe('ng2[ng1[Hello World!](transclude)](project)'); - }); - })); + // Let's use a helper function to make this simpler + bootstrap(platformBrowserDynamic(), Ng2Module, element, ng1Module).then(upgrade => { + expect(multiTrim(element.textContent)) + .toBe('ng2[ng1[Hello World!](transclude)](project)'); + }); + })); }); });