Skip to content

Commit

Permalink
fix(ivy): support attribute selectors in dynamic component creation (a…
Browse files Browse the repository at this point in the history
…ngular#31812)

This commit fixes a bug where we assumed all dynamically created
components would have tag-name selectors, so we passed through the
"tag name" to the renderer as the first index of the selector. For
components with attribute selectors, the tag name would be "", so
the renderer would try to create an element with tag name "" and
throw. Now we default to a "div" element the same way that View
Engine did.

Closes angular#31785

PR Close angular#31812
  • Loading branch information
kara authored and sabeersulaiman committed Sep 6, 2019
1 parent 2915faa commit 67153c0
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 1 deletion.
4 changes: 3 additions & 1 deletion packages/core/src/render3/component_ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ export class ComponentFactory<T> extends viewEngine_ComponentFactory<T> {
private componentDef: ComponentDef<any>, private ngModule?: viewEngine_NgModuleRef<any>) {
super();
this.componentType = componentDef.type;
this.selector = componentDef.selectors[0][0] as string;

// default to 'div' in case this component has an attribute selector
this.selector = componentDef.selectors[0][0] as string || 'div';
this.ngContentSelectors =
componentDef.ngContentSelectors ? componentDef.ngContentSelectors : [];
this.isBoundToModule = !!ngModule;
Expand Down
35 changes: 35 additions & 0 deletions packages/core/test/acceptance/view_container_ref_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,41 @@ describe('ViewContainerRef', () => {
expect(testParent.childNodes[1].textContent).toBe('hello');
}
});

it('should support attribute selectors in dynamically created components', () => {
@Component({selector: '[hello]', template: 'Hello'})
class HelloComp {
}

@NgModule({entryComponents: [HelloComp], declarations: [HelloComp]})
class HelloCompModule {
}

@Component({
template: `
<ng-container #container></ng-container>
`
})
class TestComp {
@ViewChild('container', {read: ViewContainerRef, static: false}) vcRef !: ViewContainerRef;

constructor(public cfr: ComponentFactoryResolver) {}

createComponent() {
const factory = this.cfr.resolveComponentFactory(HelloComp);
this.vcRef.createComponent(factory);
}
}

TestBed.configureTestingModule({declarations: [TestComp], imports: [HelloCompModule]});
const fixture = TestBed.createComponent(TestComp);
fixture.detectChanges();
expect(fixture.debugElement.nativeElement.innerHTML).not.toContain('Hello');

fixture.componentInstance.createComponent();
fixture.detectChanges();
expect(fixture.debugElement.nativeElement.innerHTML).toContain('Hello');
});
});

describe('insert', () => {
Expand Down

0 comments on commit 67153c0

Please sign in to comment.